<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Darren "Dazbo" Lester</title>
    <description>The latest articles on DEV Community by Darren "Dazbo" Lester (@dazbo).</description>
    <link>https://dev.to/dazbo</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F548192%2F86492fc3-866f-4a3f-8a58-de3c6f467742.jpg</url>
      <title>DEV Community: Darren "Dazbo" Lester</title>
      <link>https://dev.to/dazbo</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/dazbo"/>
    <language>en</language>
    <item>
      <title>Spec-Driven Development For-the-Win: Disposable Code, Living Blueprints, and Building Like a Boss</title>
      <dc:creator>Darren "Dazbo" Lester</dc:creator>
      <pubDate>Tue, 20 Oct 2026 10:28:53 +0000</pubDate>
      <link>https://dev.to/gde/spec-driven-development-for-the-win-disposable-code-living-blueprints-and-building-like-a-boss-2bnn</link>
      <guid>https://dev.to/gde/spec-driven-development-for-the-win-disposable-code-living-blueprints-and-building-like-a-boss-2bnn</guid>
      <description>&lt;p&gt;&lt;em&gt;Part 3 of the series "Beyond Vibe Coding: The Engineering Blueprint for Reliable AI Agents"&lt;/em&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;h3&gt;
  
  
  🗺️ The Series Roadmap: Beyond Vibe Coding
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;In 2026, software development is drowning in fragmented buzzwords: Harness Engineering, Loop Engineering, Context Engineering, Spec-Driven Development, Evaluators, and Sandboxes. Are they competing frameworks? Redundant prompt techniques? Or something fundamentally new?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This four-part series unifies these concepts into a single, cohesive architectural blueprint for building software with AI without writing code manually:&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Part 1:&lt;/strong&gt; &lt;a href="https://dev.to/gde/from-vibing-chaos-to-reliable-agents-the-what-why-and-how-of-harness-engineering-4ba0"&gt;&lt;strong&gt;From Vibing Chaos to Reliable Agents: The What, Why, and How of Harness Engineering&lt;/strong&gt;&lt;/a&gt;
We diagnose the hangover of vibe coding, unpack the paradigm shift of &lt;em&gt;shifting developer interventions left&lt;/em&gt;, establish our bedrock formula (&lt;strong&gt;Agent = Model + Harness&lt;/strong&gt;), explore the Lewis Hamilton motorsport analogy, and deconstruct the deterministic components that make up a production developer environment.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Part 2:&lt;/strong&gt; &lt;a href="https://dev.to/gde/loop-engineering-in-the-harness-autonomous-self-correcting-systems-part-2-155e"&gt;&lt;strong&gt;Loop Engineering in the Harness: Autonomous, Self-Correcting Systems&lt;/strong&gt;&lt;/a&gt;
We fire up the dynamic runtime engine of the harness: deconstructing the core loop components, establishing hybrid evaluation rubrics (deterministic tests + LLM goal fidelity + tool trajectory verification), and applying the Ratchet Principle.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Part 3: Spec-Driven Development For-the-Win: Disposable Code, Living Blueprints, and Building Like a Boss (This Article)&lt;/strong&gt;
We explore Spec-Driven Development (where code is disposable and specifications are the single source of truth), master Google Antigravity's unified harness and interactive slash commands (&lt;code&gt;/grill-me&lt;/code&gt;, &lt;code&gt;/plan&lt;/code&gt;, &lt;code&gt;/goal&lt;/code&gt;, &lt;code&gt;/boost&lt;/code&gt;, &lt;code&gt;/learn&lt;/code&gt;), and combine formal specs on disk with autonomous tactical workflows in your session.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Part 4: Scaling the Harness: Practical Loop Patterns, ADK 2 Graphs, Recursive Harness², and Harness Maintenance (Coming Soon)&lt;/strong&gt;
We bring everything together with practical loop patterns you can wire into any repo (from declarative Markdown and &lt;code&gt;loopy&lt;/code&gt; to Google ADK 2 graphs), keep context clean across iterations with short-lived subagents, explore Google Research's recursive Harness² framework, and cover ongoing harness maintenance.&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Fuel for the Engine: Replacing Vibes with Verified Intent
&lt;/h2&gt;

&lt;p&gt;In &lt;a href="https://dev.to/gde/from-vibing-chaos-to-reliable-agents-the-what-why-and-how-of-harness-engineering-4ba0"&gt;Part 1&lt;/a&gt;, we used the race car analogy for the agentic harness and built the deterministic chassis. In &lt;a href="https://dev.to/gde/loop-engineering-in-the-harness-autonomous-self-correcting-systems-part-2-155e"&gt;Part 2&lt;/a&gt;, we built the powertrain: the autonomous execution loop, hybrid evaluation rubrics, and the Ratchet Principle.&lt;/p&gt;

&lt;p&gt;Crucially, in Part 2 we established a foundational architectural discipline: &lt;strong&gt;decoupling reusable engineering guardrails from the task specification.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We centralised the "how we build" — coding standards, test-driven development mandates, security constraints, and automated linting rules — into persistent workspace context (&lt;code&gt;GEMINI.md&lt;/code&gt;, &lt;code&gt;AGENTS.md&lt;/code&gt;) and Agent Skills. That gave our loop its invariant engineering discipline.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;So what fuels the loop? What defines "what we build"?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8vnuypxfye8k95nom15m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8vnuypxfye8k95nom15m.png" alt="Fuelling the Developer Harness" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you pair rigorous engineering guardrails with vague, casual chat prompts and hand-waving, you won't get quality software. You'll get AI slop at 50 tokens a second.&lt;/p&gt;

&lt;p&gt;This is where &lt;strong&gt;Spec-Driven Development (SDD)&lt;/strong&gt; enters the frame. As Google Developer Advocate Lee Boonstra brilliantly captured in her whitepaper &lt;a href="https://www.kaggle.com/whitepaper-spec-driven-production-grade-development-in-the-age-of-vibe-coding?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;&lt;em&gt;Spec-Driven Production Grade Development in the Age of Vibe Coding&lt;/em&gt;&lt;/a&gt;, formalising the task into a structured, testable specification transforms a slop generator into a precision instrument.&lt;/p&gt;

&lt;p&gt;It also unlocks a fundamental architectural shift: &lt;strong&gt;code is disposable, but specifications are the permanent source of truth.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3nmjjilfcw60khgnsy03.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3nmjjilfcw60khgnsy03.png" alt="The Architectural Shift: Permanent Living Specifications vs Disposable Generated Code" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Because your engineering context, linters, and evaluation rubrics already govern quality, the generated source code is merely an ephemeral byproduct. If business requirements change or an implementation runs down an architectural blind alley, you don't spend days manually untangling spaghetti code. Your standing guardrails stay untouched; you sharpen the task specification, and let your harness regenerate a clean solution from first principles.&lt;/p&gt;

&lt;p&gt;In &lt;a href="https://arxiv.org/abs/2602.08111" rel="noopener noreferrer"&gt;&lt;em&gt;Spec-Driven Development for Agentic Software Engineering: Harnessing Human-Agent Teamwork&lt;/em&gt;&lt;/a&gt;, researchers demonstrated that unconstrained conversational agents inevitably suffer from &lt;strong&gt;compounding specification drift&lt;/strong&gt; — a phenomenon where tiny misunderstandings compound across successive turns. Without a fixed specification, it is virtually guaranteed that the final output will drift away from your architectural intent.&lt;/p&gt;

&lt;p&gt;SDD eliminates this drift by introducing immutable contract checkpoints at every phase, keeping the agent firmly on the rails instead of letting it wander off into the weeds.&lt;/p&gt;

&lt;p&gt;For years, the industry swung between two dysfunctional extremes: either spending months drafting bloated, upfront documentation that was obsolete before deployment, or weaponising a poor understanding of "agile" to jump straight into code with zero planning.&lt;/p&gt;

&lt;p&gt;SDD finally closes that gap. Iterating on a half-page specification with an AI partner takes five minutes. The harness then builds and verifies the code in the sandbox in ninety seconds. You inspect working software, get instant empirical feedback, update the contract, and loop. It delivers the deep architectural rigour that enterprises require, at the blistering feedback cadence that agile was always supposed to deliver.&lt;/p&gt;

&lt;p&gt;In other words, &lt;strong&gt;SDD plus an agent takes genuine agile principles to their logical conclusion&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The SDD Lifecycle as a Continuous Loop
&lt;/h2&gt;

&lt;p&gt;In an agentic workflow, clear documentation isn't cumbersome ceremony — &lt;strong&gt;it is a superpower&lt;/strong&gt;. Spec-Driven Development is emphatically not a rigid, 200-page document that gathers dust in an enterprise SharePoint graveyard. It is a continuous, living lifecycle that evolves in near real-time alongside the codebase.&lt;/p&gt;

&lt;p&gt;Let's take a look at the SDD lifecycle:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fw5rzd7or5j94h5xoeqd9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fw5rzd7or5j94h5xoeqd9.png" alt="SDD Lifecycle" width="688" height="684"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Don't let the formal diagram labels fool you into thinking this is a return to heavyweight waterfall processes. In an agentic workflow, &lt;strong&gt;Steps 1, 2, and 3 happen collaboratively in minutes&lt;/strong&gt; — often in a single conversational exchange — to produce that concise living blueprint:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Scope &amp;amp; Edge Discovery (The WHAT):&lt;/strong&gt; A quick dialogue pinning down user intent, non-goals, and boundary conditions. No 50-page PRD; just conversational clarity on what's in scope and what's out.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Interface Contracts &amp;amp; Boundaries (The HOW):&lt;/strong&gt; Nailing down the API shape, schema constraints, and Operational Boundaries (&lt;em&gt;Always Do&lt;/em&gt;, &lt;em&gt;Ask First&lt;/em&gt;, &lt;em&gt;Never Do&lt;/em&gt;) before authoring implementation code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Acceptance Criteria &amp;amp; Test Scenarios (The PROOF):&lt;/strong&gt; Declaring how success will be proven — a few lines of Gherkin or a failing test stub — giving the agent an unambiguous finish line.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automated Code Generation:&lt;/strong&gt; The agent consumes the living specification within the sandboxed harness, generating implementation code constrained strictly by the contracts and boundaries agreed in steps 1 to 3.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Testing &amp;amp; Continuous Validation:&lt;/strong&gt; Automated test runners execute unit, integration, and static analysis suites directly against the test specification. Simple code defects are patched by Part 2's inner execution loop, while discovered requirement gaps loop straight back to refine the living spec.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Concrete Artifact: A Production Spec Blueprint (&lt;code&gt;tasks/plan.md&lt;/code&gt;)
&lt;/h2&gt;

&lt;p&gt;What does a real specification look like when fed into an agentic harness?&lt;/p&gt;

&lt;p&gt;It should not be an informal prompt. It is a structured, version-controlled markdown artifact living directly in your repository.&lt;/p&gt;

&lt;p&gt;Here is a &lt;strong&gt;reference blueprint of a production &lt;code&gt;tasks/plan.md&lt;/code&gt; specification&lt;/strong&gt; for a cloud service (in this case, an audit event logger backed by Cloud Spanner):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gh"&gt;# Implementation Spec: Cloud Spanner Audit Event Logger&lt;/span&gt;

&lt;span class="gu"&gt;## 1. Architectural Scope &amp;amp; Contracts&lt;/span&gt;
&lt;span class="p"&gt;
-&lt;/span&gt; &lt;span class="gs"&gt;**Component:**&lt;/span&gt; &lt;span class="sb"&gt;`AuditEventLogger`&lt;/span&gt; service in &lt;span class="sb"&gt;`services/audit_logger.py`&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**Persistence:**&lt;/span&gt; Cloud Spanner table &lt;span class="sb"&gt;`audit_events`&lt;/span&gt; (Schema: &lt;span class="sb"&gt;`event_id STRING(36)`&lt;/span&gt;, &lt;span class="sb"&gt;`timestamp TIMESTAMP`&lt;/span&gt;, &lt;span class="sb"&gt;`actor STRING(128)`&lt;/span&gt;, &lt;span class="sb"&gt;`action STRING(64)`&lt;/span&gt;, &lt;span class="sb"&gt;`payload JSON`&lt;/span&gt;)
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**Transport:**&lt;/span&gt; Async gRPC client via &lt;span class="sb"&gt;`google-cloud-spanner`&lt;/span&gt; Python SDK

&lt;span class="gu"&gt;## 2. Three-Tier Operational Boundaries&lt;/span&gt;

&lt;span class="gu"&gt;### Always Do&lt;/span&gt;
&lt;span class="p"&gt;
-&lt;/span&gt; Enforce strict typing on all method signatures using PEP 585 standard types.
&lt;span class="p"&gt;-&lt;/span&gt; Ensure all database writes use Spanner Mutation batches (&lt;span class="sb"&gt;`spanner.insert_or_update`&lt;/span&gt;) rather than ad-hoc DML statements.
&lt;span class="p"&gt;-&lt;/span&gt; Run &lt;span class="sb"&gt;`uvx ruff check --fix .`&lt;/span&gt; and &lt;span class="sb"&gt;`uvx codespell -s`&lt;/span&gt; after any file modification.
&lt;span class="p"&gt;-&lt;/span&gt; Practice TDD: author failing test in &lt;span class="sb"&gt;`tests/test_audit_logger.py`&lt;/span&gt; before touching service code.

&lt;span class="gu"&gt;### Ask First (Human Verification Required)&lt;/span&gt;
&lt;span class="p"&gt;
-&lt;/span&gt; Adding any new third-party Python dependency to &lt;span class="sb"&gt;`pyproject.toml`&lt;/span&gt;.
&lt;span class="p"&gt;-&lt;/span&gt; Modifying Spanner DDL or altering table schemas.
&lt;span class="p"&gt;-&lt;/span&gt; Proposing changes to the shared gRPC authentication interceptor.

&lt;span class="gu"&gt;### Never Do&lt;/span&gt;
&lt;span class="p"&gt;
-&lt;/span&gt; Never hardcode service account keys, project IDs, or credentials; rely strictly on Application Default Credentials (ADC).
&lt;span class="p"&gt;-&lt;/span&gt; Never execute inline &lt;span class="sb"&gt;`python -c`&lt;/span&gt; snippets in terminal sessions.
&lt;span class="p"&gt;-&lt;/span&gt; Never catch generic &lt;span class="sb"&gt;`Exception`&lt;/span&gt; without re-raising or logging with structured traceback.

&lt;span class="gu"&gt;## 3. Phased Vertical Decomposition&lt;/span&gt;
&lt;span class="p"&gt;
-&lt;/span&gt; [ ] &lt;span class="gs"&gt;**Phase 1: Domain Models &amp;amp; Test Scaffolding**&lt;/span&gt;
&lt;span class="p"&gt;  -&lt;/span&gt; Define &lt;span class="sb"&gt;`AuditEvent`&lt;/span&gt; Pydantic / dataclass model in &lt;span class="sb"&gt;`models/audit.py`&lt;/span&gt;.
&lt;span class="p"&gt;  -&lt;/span&gt; Author unit test mocking Spanner database client in &lt;span class="sb"&gt;`tests/test_audit_logger.py`&lt;/span&gt;.
&lt;span class="p"&gt;  -&lt;/span&gt; &lt;span class="ge"&gt;*Verification:*&lt;/span&gt; &lt;span class="sb"&gt;`uv run pytest tests/test_audit_logger.py`&lt;/span&gt; runs and fails with &lt;span class="sb"&gt;`NotImplementedError`&lt;/span&gt;.
&lt;span class="p"&gt;
-&lt;/span&gt; [ ] &lt;span class="gs"&gt;**Phase 2: Service Implementation &amp;amp; Batch Mutations**&lt;/span&gt;
&lt;span class="p"&gt;  -&lt;/span&gt; Implement &lt;span class="sb"&gt;`log_event()`&lt;/span&gt; and &lt;span class="sb"&gt;`log_batch()`&lt;/span&gt; methods in &lt;span class="sb"&gt;`services/audit_logger.py`&lt;/span&gt;.
&lt;span class="p"&gt;  -&lt;/span&gt; Implement transient backoff retry logic for &lt;span class="sb"&gt;`Aborted`&lt;/span&gt; and &lt;span class="sb"&gt;`DeadlineExceeded`&lt;/span&gt; Spanner errors.
&lt;span class="p"&gt;  -&lt;/span&gt; &lt;span class="ge"&gt;*Verification:*&lt;/span&gt; &lt;span class="sb"&gt;`uv run pytest tests/test_audit_logger.py`&lt;/span&gt; passes 100%.
&lt;span class="p"&gt;
-&lt;/span&gt; [ ] &lt;span class="gs"&gt;**Phase 3: Static Analysis &amp;amp; Hygiene**&lt;/span&gt;
&lt;span class="p"&gt;  -&lt;/span&gt; Execute static analysis and spellcheck suite.
&lt;span class="p"&gt;  -&lt;/span&gt; &lt;span class="ge"&gt;*Verification:*&lt;/span&gt; Zero warnings from &lt;span class="sb"&gt;`ruff`&lt;/span&gt; and &lt;span class="sb"&gt;`codespell`&lt;/span&gt;.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice the power of the &lt;strong&gt;operational boundaries&lt;/strong&gt; (&lt;em&gt;Always Do&lt;/em&gt;, &lt;em&gt;Ask First&lt;/em&gt;, &lt;em&gt;Never Do&lt;/em&gt;). This is where harness engineering neutralises the wild unpredictability of vibe coding. The agent knows exactly where it has autonomous authority (writing tests, formatting code) and where it must yield control to the human conductor (modifying schemas, adding dependencies).&lt;/p&gt;

&lt;h3&gt;
  
  
  What vs How: The Two Layers of a Living Specification
&lt;/h3&gt;

&lt;p&gt;Now, is a single technical plan like our Spanner blueprint the only way to frame a specification? Definitely not.&lt;/p&gt;

&lt;p&gt;In production engineering, specifications often operate across two complementary layers:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;The Functional Specification (&lt;code&gt;spec.md&lt;/code&gt; — The "WHAT" &amp;amp; "WHY"):&lt;/strong&gt; User-centric and technology-agnostic. It defines the business goals, persona expectations, explicit non-goals (what the agent must &lt;em&gt;not&lt;/em&gt; build, preventing scope creep), and verifiable acceptance criteria. It deliberately avoids mentioning specific Python classes, database drivers, or file paths.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Technical Implementation Plan (&lt;code&gt;plan.md&lt;/code&gt; — The "HOW"):&lt;/strong&gt; Codebase-aware and execution-focused. It translates the functional spec into concrete file impact maps (which files to create, edit, or delete), data schemas, library dependencies with explicit versions, and ordered task checklists.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Our Spanner example above is a &lt;strong&gt;compact technical execution plan&lt;/strong&gt; — bundling architectural scope, operational boundaries, and phased vertical slices into a single actionable file for the loop.&lt;/p&gt;

&lt;p&gt;The Three-Tier Boundaries (&lt;em&gt;Always Do&lt;/em&gt;, &lt;em&gt;Ask First&lt;/em&gt;, &lt;em&gt;Never Do&lt;/em&gt;) represent a key operational pattern within that plan: they govern the agent's blast radius and autonomy envelope. As we'll explore in the next section, these boundaries can live directly inside a task plan, or be codified globally as a non-negotiable project constitution.&lt;/p&gt;

&lt;h3&gt;
  
  
  Spec Anatomy: Token Physics and Behaviour-Driven Contracts
&lt;/h3&gt;

&lt;p&gt;When crafting a specification, two practical disciplines make the difference between an agent that drifts and one that executes with surgical precision:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Token Physics &amp;amp; Formatting Science (The Hybrid Markdown + YAML Rule):&lt;/strong&gt; Large language models do not interpret abstract data structures; they process tokenised text. In recent agent compilation research (such as the &lt;em&gt;SkCC&lt;/em&gt; study highlighted in Lee Boonstra's whitepaper), LLM agents suffered up to a &lt;strong&gt;40% performance drop&lt;/strong&gt; when fed generic, unoptimised Markdown documents. For Gemini models, the sweet spot is &lt;strong&gt;Hybrid Markdown + Conditional YAML&lt;/strong&gt;. Use clean Markdown headers (&lt;code&gt;#&lt;/code&gt;, &lt;code&gt;##&lt;/code&gt;) to anchor broad system context and global narrative instructions. Meanwhile, render structured configuration, data contracts, and entity schemas (especially with nesting depth &amp;gt; 3) in &lt;strong&gt;flat, compact YAML&lt;/strong&gt; rather than verbose JSON or XML. YAML achieves significantly higher parsing accuracy for deep configurations while eliminating the heavy "reasoning format tax" of JSON closing brackets and quotes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Behaviour-Driven Development (BDD) with Gherkin:&lt;/strong&gt; Vibe prompts describe vague wishes (&lt;em&gt;"make a friendly booking system"&lt;/em&gt;). A production-grade spec describes verifiable state transitions. Wrapping acceptance criteria in declarative Gherkin syntax (&lt;code&gt;Given / When / Then&lt;/code&gt;) forces the model into a deterministic &lt;strong&gt;State → Action → Outcome&lt;/strong&gt; sequence:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight gherkin"&gt;&lt;code&gt;&lt;span class="kn"&gt;Scenario&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; Booking a table with active dietary preferences
  &lt;span class="nf"&gt;Given &lt;/span&gt;a customer with dietary preference &lt;span class="s"&gt;"gluten-free"&lt;/span&gt; recorded in session
  &lt;span class="err"&gt;When they request a reservation for 2 guests on Friday at 19&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="err"&gt;00&lt;/span&gt;
  &lt;span class="nf"&gt;Then &lt;/span&gt;verify table availability via the Cloud SQL reservation tool
  &lt;span class="nf"&gt;And &lt;/span&gt;confirm the booking, returning a structured reservation ID
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;(Side note: even standard Markdown engines natively support &lt;code&gt;gherkin&lt;/code&gt; syntax highlighting out of the box — proving just how universally recognised this format already is! Not Medium, of course!)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;By providing explicit preconditions, the exact tool to trigger, and the expected outcome, you remove all ambiguity. The agent doesn't need to guess your intent; it simply fulfils the contract.&lt;/p&gt;

&lt;h2&gt;
  
  
  Practical Tooling for Spec-Driven Development
&lt;/h2&gt;

&lt;p&gt;You don't have to invent your own specification formats or build bespoke SDD tooling from scratch. The agentic engineering community has converged on several robust frameworks, each suited to different developer workflows.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fasatnvlqz37s1i8fhtg9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fasatnvlqz37s1i8fhtg9.png" alt="SDD frameworks" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  1. The &lt;code&gt;spec-driven-development&lt;/code&gt; Skill
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;What it is:&lt;/strong&gt; An open-source Agent Skill (created by Addy Osmani) that enforces specification discipline as an autonomous conversational workflow loaded directly into your agent's context.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;How you use it:&lt;/strong&gt; Installed in your workspace (&lt;code&gt;.agents/skills/&lt;/code&gt;) or global configuration (&lt;code&gt;~/.gemini/config/skills/&lt;/code&gt;), you trigger it conversationally at the start of any feature (e.g. &lt;em&gt;"Use spec-driven development to scaffold the audit logger"&lt;/em&gt;). The agent enforces a strict 5-stage sequence (&lt;em&gt;Scope Check → Specify → Plan → Tasks → Implement&lt;/em&gt;), pausing at each gate to surface its technical assumptions:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ASSUMPTIONS I'M MAKING:
1. Target runtime is Python 3.13 managed via uv.
2. Data persistence uses Cloud Spanner with dialect GoogleSQL.
3. Authentication relies on Google Cloud ADC / IAM principal tokens.
-&amp;gt; Confirm or correct before proceeding.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;What it outputs:&lt;/strong&gt; A single, consolidated &lt;code&gt;tasks/plan.md&lt;/code&gt; file committed to your repository — exactly like our Spanner blueprint above — featuring architectural contracts, Three-Tier Boundaries (&lt;em&gt;Always Do&lt;/em&gt;, &lt;em&gt;Ask First&lt;/em&gt;, &lt;em&gt;Never Do&lt;/em&gt;), and an ordered checklist of test-verifiable tasks.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. GitHub's &lt;a href="https://github.com/github/spec-kit" rel="noopener noreferrer"&gt;&lt;code&gt;spec-kit&lt;/code&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;What it is:&lt;/strong&gt; An open-source CLI toolkit and prompt harness created by GitHub that standardises specification-first software development through dedicated commands, project-level constitutions, and multi-file dossiers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;How you use it:&lt;/strong&gt; Executed via CLI or interactive slash commands (&lt;code&gt;/speckit.specify&lt;/code&gt; → &lt;code&gt;/speckit.clarify&lt;/code&gt; → &lt;code&gt;/speckit.plan&lt;/code&gt; → &lt;code&gt;/speckit.tasks&lt;/code&gt; → &lt;code&gt;/speckit.implement&lt;/code&gt;). You run each step as an explicit command in your terminal or IDE, validating proposed designs against a non-negotiable Project Constitution (&lt;code&gt;.specify/memory/constitution.md&lt;/code&gt;). It also includes independent, lightweight workflows for &lt;strong&gt;Bug Fixing&lt;/strong&gt; (&lt;code&gt;assess&lt;/code&gt; → &lt;code&gt;fix&lt;/code&gt; → &lt;code&gt;test&lt;/code&gt;) and &lt;strong&gt;Idea Assessment&lt;/strong&gt; (&lt;code&gt;intake&lt;/code&gt; → &lt;code&gt;define&lt;/code&gt; → &lt;code&gt;decide&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;What it outputs:&lt;/strong&gt; A modular, version-controlled dossier under &lt;code&gt;specs/&amp;lt;feature-branch&amp;gt;/&lt;/code&gt; containing separated files: &lt;code&gt;spec.md&lt;/code&gt; (the user-facing WHAT), &lt;code&gt;plan.md&lt;/code&gt; and &lt;code&gt;data-model.md&lt;/code&gt; (the technical HOW), &lt;code&gt;research.md&lt;/code&gt; (library versions and decisions), and &lt;code&gt;tasks.md&lt;/code&gt; (an atomic execution checklist).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. Google's Conductor Extension
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;What it is:&lt;/strong&gt; An AI-native extension and visual workspace assistant from Google that guides developers through context gathering, specification authoring, and test generation directly inside their editor.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;How you use it:&lt;/strong&gt; As announced on the &lt;a href="https://developers.googleblog.com/evolving-spec-driven-development-conductor-now-supports-antigravity/?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;Google Developers Blog&lt;/a&gt;, Conductor now natively supports Antigravity. It lives directly inside your editor sidebar: initiating a structured context-gathering flow, clarifying ambiguous requirements, and validating test coverage before unlocking code generation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;What it outputs:&lt;/strong&gt; An established set of structured, version-controlled Markdown files — specifically &lt;code&gt;product.md&lt;/code&gt; (vision and scope), &lt;code&gt;tech-stack.md&lt;/code&gt; (dependencies and architecture), &lt;code&gt;spec.md&lt;/code&gt; (contracts and acceptance criteria), and &lt;code&gt;plan.md&lt;/code&gt; (task execution). Just like any other SDD framework, these files are committed to the repo and loaded straight into Antigravity's context window as the permanent source of truth.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Google Antigravity: The Unified Developer Harness
&lt;/h2&gt;

&lt;p&gt;Where does all of this come together in practice?&lt;/p&gt;

&lt;p&gt;Up to this point, we have talked about harness components conceptually: hierarchical context rules, MCP servers, sandboxed environments, evaluation rubrics, and living specifications. But developers need a concrete runtime to orchestrate all these moving parts into a cohesive workflow.&lt;/p&gt;

&lt;p&gt;In the Google ecosystem, that orchestrator is &lt;a href="https://antigravity.google/?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;&lt;strong&gt;Google Antigravity&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Antigravity is not another chat assistant bolted into the sidebar of an editor. It is an &lt;strong&gt;AI-native developer harness engine&lt;/strong&gt; built from the ground up around the &lt;strong&gt;Plan → Do → Verify&lt;/strong&gt; engineering cycle. Rather than expecting a single model prompt to handle everything in one turn, Antigravity operationalises harness discipline: actively coordinating the engineering environment around the model, managing context, enforcing boundaries, and verifying outcomes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Inside the Harness: What the Engine Coordinates
&lt;/h3&gt;

&lt;p&gt;Don't mistake Antigravity for a passive chat assistant that merely answers questions and suggests snippets. A true developer harness actively coordinates the engineering environment around the model:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Automatic Rule &amp;amp; Policy Enforcement (No Copy-Pasting Prompts):&lt;/strong&gt; Rather than expecting you to copy-paste prompts or manually configure system instructions, Antigravity natively discovers and binds hierarchical rule files (&lt;code&gt;~/.gemini/GEMINI.md&lt;/code&gt;, &lt;code&gt;workspace/.agents/rules/&lt;/code&gt;, and &lt;code&gt;workspace/GEMINI.md&lt;/code&gt; — which is completely interchangeable with &lt;code&gt;workspace/AGENTS.md&lt;/code&gt; depending on your team's conventions). It ensures your coding standards, package policies, and architectural requirements are deterministically bound to every model invocation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;First-Class Agent Skills &amp;amp; MCP Orchestration:&lt;/strong&gt; Antigravity was built from the ground up for progressive disclosure. It tracks installed skills via lightweight metadata headers, dynamically expanding full instruction sets and schemas only when relevant tasks are triggered. Once declared in your configuration, it natively handles tool registration, schema discovery, and execution against both local and remote MCP servers (such as &lt;code&gt;developer-knowledge&lt;/code&gt; and Cloud Logging).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Isolated Sandboxing with Blast-Radius Control:&lt;/strong&gt; Commands executed by Antigravity run inside an isolated sandbox by default. The agent has full read/write access to your workspace, but network access and modifications to host-level operating system files require explicit privilege elevation. This gives the agent freedom to compile, test, and refactor code rapidly without placing the developer's workstation at risk.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Subagent Spawning &amp;amp; Context Isolation:&lt;/strong&gt; Long-running development tasks often require diverse capabilities. When an agent needs to survey documentation across twenty web pages or perform an in-depth accessibility audit, Antigravity can spawn isolated subagents (like dedicated research or browser agents). The subagent executes its bounded task, returns a synthesised result to the parent orchestrator, and terminates — keeping the primary context window lean and focused.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Subagent-Driven Development (Task Implementers &amp;amp; Reviewers):&lt;/strong&gt; Beyond ad-hoc research, structured SDD harnesses split implementation across specialised subagent personas. Rather than cluttering the primary conversation with thousands of lines of intermediate compiler output and syntax churn, Antigravity can dispatch each task to an isolated &lt;strong&gt;Task Implementer&lt;/strong&gt; subagent with a pristine context window. Once implementation completes, an independent &lt;strong&gt;Task Reviewer&lt;/strong&gt; subagent evaluates the code against the specification contract, passing only a clean verification receipt back to the primary orchestrator.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  One Core Harness Across Five Developer Surfaces
&lt;/h3&gt;

&lt;p&gt;Now, where does this harness live?&lt;/p&gt;

&lt;p&gt;Crucially, &lt;strong&gt;Google Antigravity delivers this identical harness engine across four developer surfaces, alongside a programmatic Python SDK&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;strong&gt;Antigravity App&lt;/strong&gt; (formerly Antigravity 2.0) — a dedicated desktop application designed for intent-based building, allowing you to direct autonomous agents, review visual artifacts, and orchestrate projects without having to worry about the underlying code.&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;Antigravity IDE&lt;/strong&gt; — a standalone, AI-first code editor (built on VS Code) for developers who want a complete coding workspace with intelligent tab completions, inline refactoring, and in-editor sidebar assistance.&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;Antigravity Extension&lt;/strong&gt; — brings the complete harness directly into your existing editor of choice (VS Code, JetBrains, Visual Studio, or Zed) so you don't have to abandon your familiar tools.&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;Antigravity CLI&lt;/strong&gt; — a full Terminal User Interface (TUI) for developers who live in the command line or remote SSH sessions, and want the interactive harness experience in their terminal.&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;Antigravity SDK&lt;/strong&gt; — a Python library for programmatic orchestration, headless automation, scripted workflows, and custom multi-agent systems.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Across all these surfaces and tools, the underlying configuration engine, context rules (&lt;code&gt;~/.gemini/&lt;/code&gt; and &lt;code&gt;workspace/.agents/&lt;/code&gt;), MCP servers, and sandboxed execution runtimes are completely identical.&lt;/p&gt;

&lt;p&gt;This addresses one of the biggest roadblocks in enterprise adoption: &lt;strong&gt;the IDE lock-in barrier&lt;/strong&gt;. As I explored in &lt;a href="https://dev.to/gde/meet-the-antigravity-extension-gemini-code-assist-on-steroids-in-whatever-ide-you-love-4p1n"&gt;&lt;em&gt;Meet the Antigravity Extension: Gemini Code Assist on Steroids, in Whatever IDE You Love&lt;/em&gt;&lt;/a&gt;, tens of millions of developers — and enterprise security policies — will not simply abandon their favourite IDEs overnight. By packaging the entire unified harness into an extension for VS Code, JetBrains, and beyond, Google ensures teams get full harness intelligence without having to abandon their existing toolchains.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6opemxbleck2wnd1vxtc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6opemxbleck2wnd1vxtc.png" alt="Antigravity Surfaces and Commands" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Supercharged Harness Workflows (Slash Commands)
&lt;/h2&gt;

&lt;p&gt;Antigravity provides a number of "slash" commands out-of-the-box. Rather than typing out long prompt instructions, you can trigger key harness behaviours directly using these commands:&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;/grill-me&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;The antidote to underspecified requirements. Instead of accepting a vague prompt and guessing how to implement it, Antigravity initiates a structured, one-question-at-a-time interview to stress-test your thinking, interrogate boundary conditions, and resolve ambiguities &lt;em&gt;before&lt;/em&gt; a single file is modified.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Real-world prompt:&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/grill-me on the Spanner schema and backoff retry behaviour in tasks/plan.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;code&gt;/plan&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Switches the agent into dedicated planning mode. Rather than immediately modifying files, Antigravity surveys the codebase, maps out dependencies, and presents a structured implementation plan with verification steps for your review and sign-off before execution begins.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Real-world prompt:&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/plan refactor services/audit_logger.py to use async batch mutations with zero breaking changes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;code&gt;/goal&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Initiates an autonomous execution loop for long-running tasks. Rather than pausing after every step to ask for input, the agent works through the task list, diagnoses test failures, handles retries, and yields control only when the objective is fully achieved and verified.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Real-world prompt:&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/goal implement Phase 2 of tasks/plan.md, fix any failing pytest assertions, and ensure ruff passes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;code&gt;/boost&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Transforms a single model session into a coordinated team of subagents executing tasks or adversarial reviews in parallel. In loop engineering, &lt;code&gt;/boost&lt;/code&gt; is the easiest way to implement &lt;strong&gt;decoupled multi-agent verification&lt;/strong&gt; — pairing a builder subagent with an independent critic subagent so a single model instance never marks its own homework.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Real-world prompt:&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/boost run an adversarial security and race-condition review of our Spanner transaction handler
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;code&gt;/learn&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;The mechanical realisation of the Ratchet Principle! When you guide or correct an agent during an interactive session, running &lt;code&gt;/learn&lt;/code&gt; extracts the operational lesson and crystallises it directly into your workspace rules. The lesson is immediately persisted to disk so future sessions never repeat the mistake.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Real-world prompt:&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/learn always wrap Spanner Mutation writes in exponential backoff when catching Aborted errors
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Slash Commands Alone vs. Formal SDD
&lt;/h2&gt;

&lt;p&gt;At this point, I know what you might be thinking:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"Hold on, Dazbo. If Antigravity already gives me &lt;code&gt;/plan&lt;/code&gt; and &lt;code&gt;/goal&lt;/code&gt; out of the box, why do I need formal SDD skills like Conductor, &lt;code&gt;spec-kit&lt;/code&gt;, or the &lt;code&gt;spec-driven-development&lt;/code&gt; skill? Isn't that just extra ceremony?"&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Great question. Here's the thing: it comes down to the trade-offs between &lt;strong&gt;tactical session planning&lt;/strong&gt; and &lt;strong&gt;long-term architectural governance&lt;/strong&gt;:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Dimension&lt;/th&gt;
&lt;th&gt;Native Slash Commands Alone (&lt;code&gt;/plan&lt;/code&gt;, &lt;code&gt;/goal&lt;/code&gt;)&lt;/th&gt;
&lt;th&gt;Formal SDD Skills &amp;amp; Plugins (Conductor, &lt;code&gt;spec-kit&lt;/code&gt;, &lt;code&gt;spec-driven-development&lt;/code&gt;)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Setup &amp;amp; Friction&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Zero friction.&lt;/strong&gt; Built natively into Antigravity; available instantly with no configuration.&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Moderate ceremony.&lt;/strong&gt; Requires installing the tool and walking through the guided discovery interview (though the framework scaffolds the files and folders for you).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Persistence &amp;amp; State&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Ephemeral.&lt;/strong&gt; Plans and goal states live in the active conversation thread; they risk being lost during context compression or when starting a fresh session.&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Version-Controlled.&lt;/strong&gt; Formal specs, task checklists, and ADRs live as permanent Markdown/YAML files in the Git repo (&lt;code&gt;specs/&lt;/code&gt;, &lt;code&gt;tasks/&lt;/code&gt;).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Scope Enforcement&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Conversational.&lt;/strong&gt; The model plans dynamically, but doesn't strictly enforce pre-implementation gates or boundary contracts.&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Machine-Gated.&lt;/strong&gt; Enforces strict Phase 0 scope analysis, surface assumption checks, and Three-Tier Boundaries (&lt;em&gt;Always Do&lt;/em&gt;, &lt;em&gt;Ask First&lt;/em&gt;, &lt;em&gt;Never Do&lt;/em&gt;).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Token Overhead&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Low.&lt;/strong&gt; Directly targets the immediate task at hand without multi-phase document generation.&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Higher upfront.&lt;/strong&gt; Consumes tokens generating formal contracts and schemas before writing code.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Best Used For&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Tactical features, targeted refactors, rapid bug fixes, single-session development.&lt;/td&gt;
&lt;td&gt;System architectures, multi-agent systems, cross-team projects, mission-critical services.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  An Enterprise Option: Combining SDD with Tactical Slash Commands
&lt;/h3&gt;

&lt;p&gt;You don't always need both. For everyday feature slices, targeted refactors, or rapid bug fixes, Antigravity's native slash commands (&lt;code&gt;/plan&lt;/code&gt; and &lt;code&gt;/goal&lt;/code&gt;) provide plenty of structure with zero setup overhead. Conversely, for architectural reviews, a standalone SDD dossier alone might be all your team requires.&lt;/p&gt;

&lt;p&gt;However, when you are tackling large, multi-component enterprise initiatives, &lt;strong&gt;nesting these layers into a hybrid workflow is a powerful option&lt;/strong&gt;. You can use formal SDD as the macro-architectural envelope on disk, and Antigravity's native slash commands as the micro-execution engine in the session.&lt;/p&gt;

&lt;p&gt;Here is an example four-phase hybrid pattern you can adopt when orchestrating complex features:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Phase 1 — Macro Architecture (The Outer Spec via Formal SDD / Conductor / &lt;code&gt;spec-kit&lt;/code&gt;):&lt;/strong&gt; Before generating any implementation code, establish the enduring system blueprint on disk. Define machine-readable API contracts, data schemas, test stubs, and the operational boundary rules (&lt;code&gt;specs/api_contract.md&lt;/code&gt;, &lt;code&gt;tasks/plan.md&lt;/code&gt;). Because these are committed to version control, they survive across sessions, branches, and team members.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Phase 2 — Specification Stress-Testing (&lt;code&gt;/grill-me&lt;/code&gt;):&lt;/strong&gt; Once the initial specification is drafted, invoke &lt;code&gt;/grill-me&lt;/code&gt; against the spec file. Antigravity acts as a relentless, sceptical peer reviewer. It interrogates boundary conditions, probes error handling paths, questions concurrency models, and surfaces hidden assumptions &lt;em&gt;before&lt;/em&gt; signing off on the architecture.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Phase 3 — Autonomous Tactical Execution (&lt;code&gt;/plan&lt;/code&gt; + &lt;code&gt;/goal&lt;/code&gt; + &lt;code&gt;/boost&lt;/code&gt;):&lt;/strong&gt; With the formal spec locked, feed a single vertical slice from your task plan into &lt;code&gt;/goal&lt;/code&gt; (or &lt;code&gt;/boost&lt;/code&gt; for separated Builder/Critic verification). Antigravity's autonomous workbench takes over, executing the &lt;strong&gt;tactical inner execution loop we built in Part 2&lt;/strong&gt;: it uses &lt;code&gt;/plan&lt;/code&gt; to map out immediate file edits, executes changes inside the sandbox, validates against deterministic linters and semantic rubrics, and loops autonomously until every gate is green.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Phase 4 — Hardening the Harness (&lt;code&gt;/learn&lt;/code&gt;):&lt;/strong&gt; When the agent encounters an unexpected runtime quirk or discovers a project-specific constraint during the &lt;code&gt;/goal&lt;/code&gt; execution loop (such as a subtle gRPC serialisation rule or sandbox path issue), invoke &lt;code&gt;/learn&lt;/code&gt;. Antigravity extracts that operational lesson and crystallises it directly into &lt;code&gt;workspace/.agents/rules/&lt;/code&gt; or your root rule file (&lt;code&gt;GEMINI.md&lt;/code&gt; / &lt;code&gt;AGENTS.md&lt;/code&gt;). The ratchet clicks; the harness hardens; and the entire team permanently benefits from the discovery.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Sustainable Team Engineering: Defeating Approval Fatigue
&lt;/h3&gt;

&lt;p&gt;Adopting Spec-Driven Development doesn't just change how you interact with an AI model — it fundamentally alters team engineering culture.&lt;/p&gt;

&lt;p&gt;When teams first adopt automated coding assistants, they often fall into a trap known as &lt;strong&gt;review theatre&lt;/strong&gt;. Developers find themselves staring at a 1,200-line diff generated in three seconds, trying to manually verify every line of syntax. Developer experience studies consistently highlight that frequent AI tool users suffer significant cognitive burnout when trapped in manual code reviews. &lt;strong&gt;Eyeball inspection simply does not scale to agentic velocity.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fe52jtn3fvl65gy2p86om.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fe52jtn3fvl65gy2p86om.png" alt="Review fatigue" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;SDD breaks this cycle by establishing a clean division of responsibility:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Humans review the intent and the contracts:&lt;/strong&gt; You evaluate the architectural trade-offs, the boundary constraints, and the acceptance test scenarios.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The harness verifies the code:&lt;/strong&gt; Linters, sandboxed test suites, and evaluation rubrics verify the disposable implementation syntax.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By shifting human review from syntax nitpicking to spec and contract design, engineering teams eliminate approval fatigue while maintaining rigorous production quality. If the contracts and test scenarios are sound, and the automated verification suite passes in the sandbox, you can merge with confidence.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary &amp;amp; What's Next: Scaling the Harness
&lt;/h2&gt;

&lt;p&gt;We have now brought together our deterministic chassis (&lt;a href="https://dev.to/gde/from-vibing-chaos-to-reliable-agents-the-what-why-and-how-of-harness-engineering-4ba0"&gt;Part 1&lt;/a&gt;) and our autonomous loop engine (&lt;a href="https://dev.to/gde/loop-engineering-in-the-harness-autonomous-self-correcting-systems-part-2-155e"&gt;Part 2&lt;/a&gt;), fuelled by living specifications committed directly to the workspace (&lt;strong&gt;Part 3&lt;/strong&gt;) and orchestrated through &lt;strong&gt;Google Antigravity&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;But how do you introduce loop engineering into any existing repository in under five minutes? How do you prevent multi-turn loops from collapsing under context bloat? And what happens when you put a recursive meta-loop around the harness itself?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In &lt;strong&gt;Part 4 (The Finale)&lt;/strong&gt;, we take our harness to the next level:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The Anatomy of an Iteration:&lt;/strong&gt; How sandboxed environments, ephemeral subagents, and &lt;code&gt;LIVING_MEMORY.md&lt;/code&gt; filter out noise and beat attention dilution.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Practical Ways to Wire Loops into Any Project (And How to Combine Them):&lt;/strong&gt; From zero-code Markdown rules (&lt;code&gt;GEMINI.md&lt;/code&gt; + &lt;code&gt;RUBRIC.md&lt;/code&gt;) and &lt;code&gt;loopy&lt;/code&gt; (&lt;code&gt;LOOPS.md&lt;/code&gt;) to &lt;code&gt;/goal&lt;/code&gt; and programmatic &lt;strong&gt;Google ADK 2 graphs&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Google Research's Harness² (&lt;em&gt;Harness-Squared&lt;/em&gt;):&lt;/strong&gt; Recursive agent harnessing (&lt;code&gt;Propose&lt;/code&gt; → &lt;code&gt;Probe&lt;/code&gt; → &lt;code&gt;Compose&lt;/code&gt;) that optimises the editable components of your harness across tasks without retraining a single model weight.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enterprise Production Pillars on Google Cloud:&lt;/strong&gt; Bridging your local developer harness to cloud-scale production.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;👉 &lt;strong&gt;Continue to Part 4: Scaling the Harness: Practical Loop Patterns, ADK 2 Graphs, Recursive Harness², and Enterprise Production (Coming Soon)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;See you in the finale!&lt;/p&gt;




&lt;h2&gt;
  
  
  Before You Go
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Please share&lt;/strong&gt; 📢 this with anyone that you think will be interested. It might help them, and it really helps me!&lt;/li&gt;
&lt;li&gt;Please &lt;strong&gt;give me loads of claps&lt;/strong&gt;! 👏 (Just hold down the clap button.)&lt;/li&gt;
&lt;li&gt;Please &lt;strong&gt;leave a comment&lt;/strong&gt; 💬. Interaction is good!&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Add a star&lt;/strong&gt; ⭐ on my repos!&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Follow&lt;/strong&gt; 👉 and &lt;strong&gt;subscribe&lt;/strong&gt; 🔔, so you don't miss my content.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  References and Useful Links
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Spec-Driven Development
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://codelabs.developers.google.com/sdd-adk-antigravity?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;Spec-Driven ADK Agent Development with Antigravity and Spec-kit | Google Codelabs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://codelabs.developers.google.com/codelabs/getting-started-with-spec-driven-development-in-antigravity?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;Getting started with Spec Driven Development in Antigravity | Google Codelabs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://codelabs.developers.google.com/sdd-agy-cli?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;Spec-Driven Development with Antigravity CLI — Structured Agent Workflows with Skills and MCP | Google Codelabs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developers.googleblog.com/evolving-spec-driven-development-conductor-now-supports-antigravity/?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;&lt;em&gt;Evolving Spec-Driven Development: Conductor Now Supports Antigravity&lt;/em&gt; | Google Developers Blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.kaggle.com/whitepaper-spec-driven-production-grade-development-in-the-age-of-vibe-coding?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;&lt;em&gt;Spec-Driven Production Grade Development in the Age of Vibe Coding&lt;/em&gt; by Lee Boonstra (Google)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://arxiv.org/abs/2602.08111" rel="noopener noreferrer"&gt;&lt;em&gt;Spec-Driven Development for Agentic Software Engineering: Harnessing Human-Agent Teamwork&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/github/spec-kit" rel="noopener noreferrer"&gt;&lt;code&gt;github/spec-kit&lt;/code&gt;: Toolkit to help you get started with Spec-Driven Development&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/addyosmani/agent-skills/tree/main/skills/spec-driven-development" rel="noopener noreferrer"&gt;&lt;code&gt;spec-driven-development&lt;/code&gt; skill by Addy Osmani&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Google Antigravity &amp;amp; Ecosystem
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://antigravity.google/docs/home/?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;Google Antigravity Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://antigravity.google/blog/introducing-google-antigravity?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;Introducing Google Antigravity | Google Antigravity Blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/google-cloud/the-ai-native-developer-experience-part-2-harness-engineering-with-google-antigravity-7fb72dab243f" rel="noopener noreferrer"&gt;&lt;em&gt;The AI-Native Developer Experience, Part 2: Harness Engineering with Google Antigravity&lt;/em&gt; by Jaroslav Pantsjoha&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Dazbo's Related Articles
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.to/gde/from-vibing-chaos-to-reliable-agents-the-what-why-and-how-of-harness-engineering-4ba0"&gt;&lt;em&gt;From Vibing Chaos to Reliable Agents: The What, Why, and How of Harness Engineering (Part 1)&lt;/em&gt; by Dazbo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/gde/loop-engineering-in-the-harness-autonomous-self-correcting-systems-part-2-155e"&gt;&lt;em&gt;Loop Engineering in the Harness: Autonomous, Self-Correcting Systems (Part 2)&lt;/em&gt; by Dazbo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/gde/meet-the-antigravity-extension-gemini-code-assist-on-steroids-in-whatever-ide-you-love-4p1n"&gt;&lt;em&gt;Meet the Antigravity Extension: Gemini Code Assist on Steroids, in Whatever IDE You Love&lt;/em&gt; by Dazbo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/gde/dialling-our-agents-to-11-agent-skills-you-need-to-be-using-2o2k"&gt;&lt;em&gt;Dialling Our Agents to 11: Agent Skills You Need to be Using!&lt;/em&gt; by Dazbo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dazbo.co.uk" rel="noopener noreferrer"&gt;Dazbo's Portfolio&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>generativeaitools</category>
      <category>googlegemini</category>
      <category>specdrivendevelopmen</category>
      <category>harnessengineering</category>
    </item>
    <item>
      <title>Automated GitHub Code Reviews Using Google Gemini Update: Enterprise-Ready, Multimodal, and Battle-Hardened</title>
      <dc:creator>Darren "Dazbo" Lester</dc:creator>
      <pubDate>Mon, 19 Oct 2026 05:34:22 +0000</pubDate>
      <link>https://dev.to/gde/automated-github-code-reviews-using-google-gemini-update-enterprise-ready-multimodal-and-1phi</link>
      <guid>https://dev.to/gde/automated-github-code-reviews-using-google-gemini-update-enterprise-ready-multimodal-and-1phi</guid>
      <description>&lt;p&gt;You are in &lt;strong&gt;Part 2&lt;/strong&gt; of the series &lt;strong&gt;&lt;em&gt;"Automated GitHub Code Reviews Using Google Gemini"&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;h3&gt;
  
  
  🗺️ Series Navigation
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Part 1:&lt;/strong&gt; &lt;a href="https://dev.to/gde/automated-github-code-reviews-using-google-gemini-4l0f"&gt;&lt;strong&gt;Automated GitHub Code Reviews Using Google Gemini&lt;/strong&gt;&lt;/a&gt; — Why I built a super-fast, native composite GitHub Action to replace Google's sunsetted &lt;code&gt;run-gemini-cli&lt;/code&gt; and Gemini Code Assist integrations, and how to get up and running in three minutes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Part 2: Enterprise-Ready AI Code Reviews &amp;amp; Issue Triage with Google Gemini (This Article)&lt;/strong&gt; — How the action evolved from a fast weekend replacement into an enterprise-grade, multimodal code review and triage engine — featuring Gemini 3.8 Flash, visual PR diffing, bounded dynamic context selection, Gemini Enterprise Agent Platform billing attribution, supply-chain hardening, and battle-tested production fixes.&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Back for the Update!
&lt;/h2&gt;

&lt;p&gt;Howdy friends, and welcome back!&lt;/p&gt;

&lt;p&gt;When I published &lt;a href="https://dev.to/gde/automated-github-code-reviews-using-google-gemini-4l0f"&gt;Part 1&lt;/a&gt; back in July, I had a very specific itch to scratch. Google had just turned off the lights on both &lt;code&gt;run-gemini-cli&lt;/code&gt; and the consumer Gemini Code Assist GitHub integration as part of the transition to the &lt;a href="https://antigravity.google/?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;Google Antigravity suite&lt;/a&gt;. And consequently, my automated agentic pull request reviews stopped working. Sad times.&lt;/p&gt;

&lt;p&gt;So, I rolled up my sleeves...&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7njx54u5exan9znvcmwy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7njx54u5exan9znvcmwy.png" alt="Darren: Sleeves rolled up, ready to review code" width="800" height="1198"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(Okay, that's actually an attempt at using AI to put me in a Don Johnson outfit.)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;... And built a drop-in replacement: the &lt;a href="https://github.com/derailed-dash/gemini-review-action" rel="noopener noreferrer"&gt;&lt;strong&gt;Gemini PR Review &amp;amp; Triage Action&lt;/strong&gt;&lt;/a&gt; (also available directly on the &lt;a href="https://github.com/marketplace/actions/dazbo-s-gemini-code-review-issue-triage" rel="noopener noreferrer"&gt;GitHub Marketplace&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Since launching Part 1, something awesome happened. Not only did I start dogfooding the action heavily across every single repository I maintain, but developers in the community started adopting it — and &lt;strong&gt;it is now actively running in production inside at least one enterprise organisation&lt;/strong&gt;!&lt;/p&gt;

&lt;p&gt;A massive shoutout here goes to my fellow Google Developer Expert (GDE), &lt;a href="https://github.com/SaschaHeyer" rel="noopener noreferrer"&gt;&lt;strong&gt;Sascha Heyer&lt;/strong&gt;&lt;/a&gt;. Sascha rolled the action out across real production repositories, battle-tested it against enterprise edge cases, and contributed a phenomenal series of pull requests — from real-dollar cost estimation and Gemini Enterprise Agent Platform billing labels to automated review thread resolution, per-file content caps, competing bot filtering, and supply-chain lockfile hardening.&lt;/p&gt;

&lt;p&gt;Through dozens of releases (taking us from &lt;code&gt;v1.4&lt;/code&gt; all the way to &lt;code&gt;v1.8.3&lt;/code&gt;), this collaboration has transformed the tool from a "fast drop-in replacement" into what I genuinely believe is the &lt;strong&gt;de facto Google Gemini-based code reviewer and issue triager for GitHub&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Even better: it is &lt;strong&gt;100% free and open-source&lt;/strong&gt;. There are no SaaS subscriptions and no per-seat licensing fees. You simply bring your own Gemini API key or Google Cloud project, and you pay only for the raw tokens you consume — which, thanks to our built-in context caching, typically works out to &lt;strong&gt;$0.02 to $0.04 per review&lt;/strong&gt;!&lt;/p&gt;

&lt;p&gt;In this post, I'm going to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Recap the What, the Why, and the Unique Selling Points (USPs)&lt;/strong&gt; for anyone new to the party.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Share the complete current feature list&lt;/strong&gt; so you can see everything the action packs under the bonnet today.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deep-dive into the major new features, architectural upgrades, and battle-hardened bug fixes&lt;/strong&gt; we've shipped since Part 1 — including why this solution is now thoroughly &lt;strong&gt;enterprise-ready&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Grab a piña colada (or a strong coffee), and let's dive in!&lt;/p&gt;




&lt;h2&gt;
  
  
  Recap: The What, The Why, and The USPs
&lt;/h2&gt;

&lt;p&gt;If you missed &lt;a href="https://dev.to/gde/automated-github-code-reviews-using-google-gemini-4l0f"&gt;Part 1&lt;/a&gt;, here is the sixty-second elevator pitch on why automated AI code reviews in CI/CD are such a game-changer — and why this specific action hits different.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F55qnkoz6h3sanox4lv7u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F55qnkoz6h3sanox4lv7u.png" alt="Automated Code Review Pipeline with Gemini AI" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The Problem with Traditional (and Local AI) Code Reviews
&lt;/h3&gt;

&lt;p&gt;In a traditional workflow, you open a Pull Request and wait hours (or days) for a human colleague to context-switch away from their own work and review your code. When they finally get to it, human reviews are notoriously variable: some reviewers rubber-stamp a 500-line diff with "LGTM", while others bikeshed variable names and miss a glaring SQL injection vulnerability.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;"Ah,"&lt;/em&gt; you might say, &lt;em&gt;"but I already use an AI coding assistant in my IDE!"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Me too! I live in Google Antigravity every day. But relying solely on your local IDE agent to review the code it just helped you write introduces a massive blind spot: &lt;strong&gt;Session Bias&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. The "Clean Slate" Advantage
&lt;/h3&gt;

&lt;p&gt;When you pair-programme with an AI assistant in your IDE, that agent accumulates your entire conversational history. It knows what you tried, why you took a shortcut, and what compromises you made to get the tests passing. Because it understands your &lt;em&gt;intent&lt;/em&gt; so well, it frequently forgives subtle regressions, missing edge cases, or architectural drift.&lt;/p&gt;

&lt;p&gt;By running our Gemini code reviewer inside a &lt;strong&gt;GitHub Action on every Pull Request&lt;/strong&gt;, the reviewer starts with a &lt;strong&gt;completely clean slate&lt;/strong&gt;. It has zero knowledge of your local chat history or how much you struggled with a module. It objectively evaluates the raw git diff against your repository's codebase context and coding standards. Time and time again, this stateless reviewer catches bugs, security gaps, and documentation discrepancies that my local IDE session glossed right over!&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Blazing Speed: Native Composite Action + Astral's &lt;code&gt;uv&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Legacy actions (like the old &lt;code&gt;run-gemini-cli&lt;/code&gt;) built or pulled hefty Docker containers on every single run, or used sluggish &lt;code&gt;pip install&lt;/code&gt; steps that burned through GitHub Actions runner minutes before a single token was ever sent to Gemini.&lt;/p&gt;

&lt;p&gt;I architected &lt;code&gt;gemini-review-action&lt;/code&gt; as a &lt;strong&gt;native Composite Action&lt;/strong&gt; powered by Astral's blazingly fast &lt;strong&gt;&lt;code&gt;uv&lt;/code&gt;&lt;/strong&gt; package manager. There are no Docker container builds and no slow dependency resolution phases. The environment boots in a couple of seconds and posts line-specific review feedback almost immediately.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Deep Context + 90% Cost Savings via Gemini Context Caching
&lt;/h3&gt;

&lt;p&gt;Most basic AI review scripts only feed the raw &lt;code&gt;git diff&lt;/code&gt; to the model. Without knowing what the rest of your repository looks like, an LLM can't tell if a change breaks an interface defined in another module or violates your project's architectural patterns.&lt;/p&gt;

&lt;p&gt;Our action features a &lt;strong&gt;Hybrid Codebase Context Engine&lt;/strong&gt; paired with &lt;strong&gt;Stateless Gemini Context Caching&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;For repositories under 1.5 MB of text, it loads the &lt;strong&gt;entire codebase&lt;/strong&gt; into context (&lt;em&gt;Full Context Mode&lt;/em&gt;).&lt;/li&gt;
&lt;li&gt;For massive repositories and monorepos over 1.5 MB, it switches to &lt;em&gt;Sparse Context Mode&lt;/em&gt;, feeding the full directory tree, core manifests/documentation (&lt;code&gt;README.md&lt;/code&gt;, &lt;code&gt;ARCHITECTURE.md&lt;/code&gt;, &lt;code&gt;AGENTS.md&lt;/code&gt;, &lt;code&gt;pyproject.toml&lt;/code&gt;, etc.), and dynamically selecting the most relevant sister modules.&lt;/li&gt;
&lt;li&gt;Whenever repository context exceeds ~32k tokens (about 100K characters), the action provisions an ephemeral, server-side &lt;strong&gt;Gemini Context Cache&lt;/strong&gt; (&lt;code&gt;CachedContent&lt;/code&gt;). Subsequent PR pushes and multi-turn tool calls reuse that cache handle automatically — delivering a &lt;strong&gt;90% discount on cached input tokens&lt;/strong&gt; without requiring any local runner disk persistence. &lt;em&gt;(Enterprise DLP Note: On Gemini Enterprise Agent Platform, the cache is strictly tenant-isolated within your Google Cloud project and region, bounded by an automatic 1-hour TTL, and fully covered by Google Cloud's zero-training enterprise data governance commitments.)&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The Complete Feature Matrix (What's in the Box Today)
&lt;/h2&gt;

&lt;p&gt;Before we unpack the new engineering deep-dives, here is the complete summary of what &lt;strong&gt;Dazbo's Gemini PR Review &amp;amp; Triage Action (currently at version &lt;code&gt;1.8.3&lt;/code&gt;)&lt;/strong&gt; gives you right out of the box:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkw7zy0dl6omp19z0jsy3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkw7zy0dl6omp19z0jsy3.png" alt="Gemini PR Review &amp;amp; Triage Features Overview" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Core Review &amp;amp; Triage Capabilities
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;AI-Powered Pull Request Reviews&lt;/strong&gt;: Constructive, severity-graded (&lt;code&gt;🔴&lt;/code&gt; Critical, &lt;code&gt;🟠&lt;/code&gt; High, &lt;code&gt;🟡&lt;/code&gt; Medium, &lt;code&gt;🟢&lt;/code&gt; Low), line-specific inline feedback powered by the latest Gemini Flash model (currently &lt;strong&gt;&lt;code&gt;gemini-3.8-flash&lt;/code&gt;&lt;/strong&gt;) by default.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;One-Click Interactive Suggestions&lt;/strong&gt;: Formats exact code fixes inside native GitHub &lt;code&gt;suggestion&lt;/code&gt; blocks so developers can commit fixes directly in the GitHub UI with a single click.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multi-Axis Quality Framework&lt;/strong&gt;: Evaluates every PR systematically across five core engineering axes: &lt;em&gt;Correctness &amp;amp; Verification&lt;/em&gt;, &lt;em&gt;Readability &amp;amp; Simplicity&lt;/em&gt;, &lt;em&gt;Architecture &amp;amp; System Design&lt;/em&gt;, &lt;em&gt;Security &amp;amp; Data Hardening&lt;/em&gt;, and &lt;em&gt;Performance &amp;amp; Efficiency&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Holistic Documentation &amp;amp; Blog Review&lt;/strong&gt;: Evaluates Markdown documentation, READMEs, ADRs, and technical articles alongside source code for accuracy and completeness.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automated Issue Triage&lt;/strong&gt;: Dynamically classifies, prioritises, and applies repository labels to incoming or reopened GitHub issues based on issue descriptions, discussion comments, and attached screenshots.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;On-Demand &lt;code&gt;/gemini-review&lt;/code&gt; Trigger&lt;/strong&gt;: Re-trigger reviews at any time via PR comments, protected by strict &lt;code&gt;OWNER&lt;/code&gt;, &lt;code&gt;MEMBER&lt;/code&gt;, and &lt;code&gt;COLLABORATOR&lt;/code&gt; authorisation guards so random internet strangers can't drain your API quota.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Multimodal &amp;amp; Context Intelligence
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Multimodal Context &amp;amp; Visual PR Diffing&lt;/strong&gt;: Automatically extracts local images and PDFs referenced in Markdown files, and performs &lt;strong&gt;side-by-side visual PR diffing&lt;/strong&gt; (&lt;code&gt;base_sha&lt;/code&gt; vs &lt;code&gt;head_sha&lt;/code&gt;) whenever images (&lt;code&gt;.png&lt;/code&gt;, &lt;code&gt;.jpg&lt;/code&gt;, &lt;code&gt;.webp&lt;/code&gt;, &lt;code&gt;.gif&lt;/code&gt;, &lt;code&gt;.svg&lt;/code&gt;) are modified in a PR.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multimodal Issue Triage (Remote Screenshots)&lt;/strong&gt;: Automatically extracts and securely fetches remote screenshots embedded in GitHub issues (including private repo &lt;code&gt;user-attachments&lt;/code&gt;) so Gemini can visually inspect UI bug reports and stack-trace screenshots.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deterministic Image Downscaling&lt;/strong&gt;: Automatically resizes large images (&amp;gt;600 KB) down to a maximum of 300 KB before sending to Gemini, protecting your token budget and keeping latency low while passing SVGs and PDFs through lossless.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hybrid Codebase Context &amp;amp; Bounded Dynamic Selection&lt;/strong&gt;: Seamless switching between Full Context Mode and Sparse Context Mode, using proximity/import heuristics and a 4-tier architectural selector to pick the best sister files in large monorepos.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Per-File Content Truncation &amp;amp; Token Budget Safeguards&lt;/strong&gt;: Caps individual massive files (like generated OpenAPI schemas) at 128 KB and runs preflight token checks so a single huge file never crashes your review.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Google Developer Knowledge MCP Integration&lt;/strong&gt;: Queries official, live Google documentation (for Google Cloud, Gemini, Firebase, Android, etc.) via Model Context Protocol (MCP) during the review (automatically activated when the Developer Knowledge API is enabled on your API key or GCP project).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;On-Demand Agent Skills Registry&lt;/strong&gt;: Dynamically discovers and loads relevant coding standards from &lt;code&gt;.agents/skills/&lt;/code&gt;. And a curated set of starter skills for Google Cloud, ADK, and Gemini APIs are already bundled.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Conversational Memory &amp;amp; Workflow Automation
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;PR Comment &amp;amp; Discussion Thread History&lt;/strong&gt;: Retrieves prior inline review threads and PR comments across commits. Follows an opinionated resolution matrix: celebrates resolved items (&lt;code&gt;### ✅ Resolved Items from Prior Reviews&lt;/code&gt;), respects developer deferrals and architectural justifications, and re-flags silently ignored issues.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Auto-Resolving Addressed GitHub Threads&lt;/strong&gt;: Optionally resolves GitHub review conversation threads automatically (&lt;code&gt;resolve_addressed_threads: 'true'&lt;/code&gt;) once Gemini verifies the fix, unblocking &lt;em&gt;"Require conversation resolution before merging"&lt;/em&gt; branch protection rules.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Competing Bot Author Exclusion&lt;/strong&gt;: Filter out comments from secondary bots (&lt;code&gt;exclude_comment_authors: 'claude[bot]'&lt;/code&gt;) so your Gemini review remains genuinely independent and you don't pay input tokens to process another bot's prose.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Smart Inline-Suggestion Commit Skipping&lt;/strong&gt;: Automatically detects commits generated by clicking "Commit suggestion" in the GitHub UI and skips redundant re-reviews (&lt;code&gt;skip_inline_suggestions: 'true'&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Customisation, FinOps &amp;amp; Enterprise Security
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Zero-Config Agentic Installation Skill&lt;/strong&gt;: Equip your IDE agent via &lt;code&gt;npx skills add derailed-dash/gemini-review-action -y -g --skill install-gemini-code-review-action&lt;/code&gt;, then simply ask it to &lt;em&gt;"Set up Gemini review in this repo"&lt;/em&gt; — your agent handles configuration preferences, template generation, and secret setup guidance automatically.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Extending vs Replacing Guardrails&lt;/strong&gt;: Easily append organisation- or team-specific rules via &lt;code&gt;.github/review-instruction-additions.md&lt;/code&gt; or the &lt;code&gt;custom_instructions&lt;/code&gt; workflow input without losing the built-in quality framework — or you can override the entire prompt via &lt;code&gt;.github/commands/gemini-review.toml&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Configurable Personas &amp;amp; Locales&lt;/strong&gt;: Choose your reviewer's language (&lt;code&gt;English (UK)&lt;/code&gt; by default) and personality (&lt;code&gt;straight&lt;/code&gt;, &lt;code&gt;dazbo&lt;/code&gt;, &lt;code&gt;palpatine&lt;/code&gt;, or &lt;code&gt;rick&lt;/code&gt;). Careful now... Palpatine is &lt;em&gt;not very forgiving.&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4hx4meiyu3m9ouoczb8l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4hx4meiyu3m9ouoczb8l.png" alt="Vader reviewing code: " width="800" height="534"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Reasoning &amp;amp; Thinking Budget Control&lt;/strong&gt;: Defaults to &lt;strong&gt;dynamic thinking&lt;/strong&gt; (the recommended out-of-the-box setting for PR reviews, letting Gemini scale reasoning to match diff complexity). You can also clamp &lt;code&gt;thinking_level&lt;/code&gt; (&lt;code&gt;low&lt;/code&gt;, &lt;code&gt;medium&lt;/code&gt;, &lt;code&gt;high&lt;/code&gt;, or an exact integer token budget) for predictable FinOps cost ceilings, or set it to &lt;code&gt;'off'&lt;/code&gt; to make Issue Triage blazing fast and ultra-cheap.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tokenomics &amp;amp; Dollar Cost Telemetry&lt;/strong&gt;: Appends a collapsible table to every review breaking down uncached input, cached input, comment history, thinking tokens, output tokens, and the estimated dollar cost.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enterprise Keyless Authentication (WIF)&lt;/strong&gt;: Full support for Google Cloud &lt;strong&gt;Workload Identity Federation (WIF)&lt;/strong&gt; and Application Default Credentials (ADC) via Gemini Enterprise Agent Platform (formerly Vertex AI) — zero long-lived API keys required!&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gemini Enterprise Agent Platform Billing Labels&lt;/strong&gt;: Automatically tags Enterprise Agent Platform requests with &lt;code&gt;component&lt;/code&gt; and &lt;code&gt;repo&lt;/code&gt; (plus custom &lt;code&gt;billing_labels&lt;/code&gt; like &lt;code&gt;team=platform,cost_centre=engineering&lt;/code&gt;) for granular FinOps chargeback in BigQuery billing exports.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Supply-Chain &amp;amp; Runtime Hardening&lt;/strong&gt;: Enforces immutable dependency lockfiles (&lt;code&gt;uv run --locked&lt;/code&gt;), SHA-pinned internal actions, path-traversal containment, and automatic fork PR skipping.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Enterprise-Ready by Design: Security, Governance, and FinOps
&lt;/h2&gt;

&lt;p&gt;When hobbyists pick a GitHub Action, they just want to paste an API key into a secret and see comments appear on their PR. When enterprise platform and security teams evaluate a GitHub Action, they ask a very different set of questions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;em&gt;"How do we authenticate without storing static, long-lived API keys across 200 repositories?"&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;"How do we attribute AI spend back to specific business units, teams, and repositories in our Cloud Billing export?"&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;"What stops a malicious dependency drift or an untrusted fork PR from exfiltrating credentials?"&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These aren't theoretical questions — this reviewer is already deployed in production at an enterprise organisation, and many of the capabilities below were forged directly from real-world enterprise governance requirements. Let's look at the key pillars.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkabi0xt0mqwyi22gfy0x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkabi0xt0mqwyi22gfy0x.png" alt="Enterprise Governance: Keyless WIF &amp;amp; FinOps Attribution" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Keyless Enterprise Auth with Workload Identity Federation (WIF)
&lt;/h3&gt;

&lt;p&gt;Static API keys (&lt;code&gt;GEMINI_API_KEY&lt;/code&gt;) are great for quick personal setups. But in an enterprise environment, long-lived credentials stored in GitHub Secrets are a compliance headache. Somebody has to rotate them, audit them, and worry about them leaking.&lt;/p&gt;

&lt;p&gt;Because our action is built on the modern &lt;code&gt;google-genai&lt;/code&gt; SDK, it natively supports &lt;strong&gt;Google Cloud Workload Identity Federation (WIF)&lt;/strong&gt; with &lt;strong&gt;Application Default Credentials (ADC)&lt;/strong&gt; with Gemini Enterprise Agent Platform (formerly Vertex AI).&lt;/p&gt;

&lt;p&gt;Instead of generating a static key, your GitHub Actions runner requests a short-lived OIDC token from GitHub and exchanges it via &lt;code&gt;google-github-actions/auth&lt;/code&gt; for an ephemeral Google Cloud access token scoped to a specific Service Account:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;review&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;permissions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;contents&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;read&lt;/span&gt;
      &lt;span class="na"&gt;pull-requests&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;write&lt;/span&gt;
      &lt;span class="na"&gt;id-token&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;write&lt;/span&gt; &lt;span class="c1"&gt;# Required for WIF OIDC token exchange&lt;/span&gt;

    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Checkout repository&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v6&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;ref&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ github.event.pull_request.head.sha || format('refs/pull/{0}/head', github.event.issue.number) }}&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Authenticate to Google Cloud via WIF&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;google-github-actions/auth@v2&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;workload_identity_provider&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;projects/123456789012/locations/global/workloadIdentityPools/${{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;secrets.WIF_POOL_ID&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}/providers/${{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;secrets.WIF_PROVIDER_ID&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}'&lt;/span&gt;
          &lt;span class="na"&gt;service_account&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;${{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;secrets.GCP_SERVICE_ACCOUNT&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}'&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Run Gemini Review Action&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;derailed-dash/gemini-review-action@v1&lt;/span&gt;
        &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;GOOGLE_GENAI_USE_VERTEXAI&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;True"&lt;/span&gt;
          &lt;span class="na"&gt;GOOGLE_CLOUD_PROJECT&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;my-enterprise-project-id"&lt;/span&gt;
          &lt;span class="na"&gt;GOOGLE_CLOUD_LOCATION&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;global"&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;github_token&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.GITHUB_TOKEN }}&lt;/span&gt;
          &lt;span class="na"&gt;gemini_model&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;gemini-3.8-flash'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why this matters for the enterprise:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Zero static secrets&lt;/strong&gt;: Credentials live for minutes and expire automatically when the job finishes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;IAM &amp;amp; VPC-SC Governance&lt;/strong&gt;: All Gemini API calls route through your Google Cloud project, meaning they respect your organisation's IAM policies, data residency regions, Cloud Audit Logs, and VPC Service Controls.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. FinOps Transparency: Real Dollar Cost Estimation &amp;amp; Gemini Enterprise Agent Platform Billing Labels
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;ROI is paramount.&lt;/strong&gt; If a solution costs too much or you can't measure what it costs, it's bad architecture.&lt;/p&gt;

&lt;p&gt;In Part 1, our telemetry block reported raw token counts. That was useful, but as fellow GDE &lt;strong&gt;Sascha Heyer&lt;/strong&gt; rightly pointed out when he contributed PR #33, developers and engineering leaders don't pay their cloud bills in tokens — they pay in dollars!&lt;/p&gt;

&lt;p&gt;We upgraded the telemetry engine (&lt;code&gt;gemini_review/pricing.py&lt;/code&gt;) to calculate and print the &lt;strong&gt;estimated dollar cost&lt;/strong&gt; on every single review, broken down by uncached input, cached input (at the 90% discount rate), thinking/reasoning tokens, and response output tokens:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8kx802hk6thpzkhbd5pp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8kx802hk6thpzkhbd5pp.png" alt="Automated PR Review Output with Dollar Cost Telemetry" width="752" height="863"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Notice a couple of deliberate engineering choices here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;No Silent Guessing&lt;/strong&gt;: If you configure an experimental or future model that isn't in our pricing table yet, the action reports the token counts and omits the dollar figure rather than borrowing another model's rate. A missing number is obvious; a wrong number is dangerous.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Time-Boxed Introductory Rates&lt;/strong&gt;: Models like &lt;code&gt;gemini-3.8-flash&lt;/code&gt; have promotional introductory pricing ($0.75 / $3.75 per 1M tokens through &lt;code&gt;2026-12-31&lt;/code&gt;, reverting to $1.50 / $7.50 afterwards). We encoded the promotional expiry dates directly into the pricing engine data structures, and the review footnote explicitly states which rate was applied. And if your enterprise has negotiated custom flat rates or uses Batch/Flex tiers, you can override the table via &lt;code&gt;GEMINI_RATE_INPUT&lt;/code&gt; and &lt;code&gt;GEMINI_RATE_OUTPUT&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Answering the FinOps Question at Scale: Cloud Billing Labels (&lt;code&gt;billing_labels&lt;/code&gt;)
&lt;/h4&gt;

&lt;p&gt;Knowing that PR #42 cost $0.03 is great for a developer. But a Head of Platform Engineering needs to answer a different question: &lt;strong&gt;"What did AI code reviews cost across our 150 repositories this month, broken down by engineering team?"&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You shouldn't have to scrape GitHub PR comments to answer a FinOps question. So we added native &lt;strong&gt;Gemini Enterprise Agent Platform Billing Labels&lt;/strong&gt; (&lt;code&gt;gemini_review/billing_labels.py&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Whenever you run on Gemini Enterprise Agent Platform (Vertex AI), the action automatically attaches sanitised GCP billing labels to every &lt;code&gt;generate_content&lt;/code&gt; request:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;component: gemini-review-action&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;repo: owner_repo&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Even better, you can pass custom chargeback dimensions via the &lt;code&gt;billing_labels&lt;/code&gt; workflow input:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Run Gemini Review Action&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;derailed-dash/gemini-review-action@v1&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;github_token&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.GITHUB_TOKEN }}&lt;/span&gt;
          &lt;span class="na"&gt;billing_labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;team=platform,cost_centre=engineering,env=ci'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;(Pro-Tip: We deliberately did &lt;strong&gt;not&lt;/strong&gt; make the PR number a default label, because high-cardinality labels turn your BigQuery billing export into a noisy mess. And if you're using a Google AI Studio API key instead of Gemini Enterprise Agent Platform, the action cleanly omits the &lt;code&gt;labels&lt;/code&gt; parameter.)&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Supply-Chain Security &amp;amp; Fork PR Hardening
&lt;/h3&gt;

&lt;p&gt;A code review action holds &lt;code&gt;pull-requests: write&lt;/code&gt; permissions and runs against untrusted PR branches. If you aren't careful, that's a prime target for supply-chain attacks. Here is how we locked it down:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Enforced Lockfiles (&lt;code&gt;uv run --locked&lt;/code&gt;)&lt;/strong&gt;: Previously, running &lt;code&gt;uv run --project&lt;/code&gt; would silently resolve and rewrite &lt;code&gt;uv.lock&lt;/code&gt; at runtime if &lt;code&gt;pyproject.toml&lt;/code&gt; drifted. That meant even if an enterprise consumer pinned our action to an immutable 40-character Git commit SHA, a transitive PyPI dependency could theoretically change at runtime. So we enforced &lt;code&gt;uv run --locked&lt;/code&gt; and pinned all nested setup actions (&lt;code&gt;actions/setup-python&lt;/code&gt; and &lt;code&gt;astral-sh/setup-uv&lt;/code&gt;) to exact commit SHAs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Untrusted Fork PR Safeguards&lt;/strong&gt;: By default, GitHub strips repository secrets from fork PRs to prevent untrusted contributors from accessing API keys. If an action tries to run automatically on a fork without secrets, it crashes with an authentication error and paints the contributor's PR with an ugly red &lt;code&gt;❌&lt;/code&gt;. Our starter workflows solve this gracefully:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Clean skips on forks&lt;/strong&gt;: The workflow guards automatic runs (&lt;code&gt;github.event.pull_request.head.repo.full_name == github.repository&lt;/code&gt;), quietly skipping external forks so CI status checks stay green.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Maintainer on-demand trigger&lt;/strong&gt;: Once a repository maintainer (&lt;code&gt;OWNER&lt;/code&gt;, &lt;code&gt;MEMBER&lt;/code&gt;, &lt;code&gt;COLLABORATOR&lt;/code&gt;) inspects the fork code, they can safely trigger Gemini by typing &lt;code&gt;/gemini-review&lt;/code&gt; in a PR comment — which runs under their authenticated context with full access to secrets.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Path Traversal Containment&lt;/strong&gt;: Every file path, Markdown image link, and skill reference loaded by the action is strictly validated against the workspace root. An attacker cannot craft a malicious Markdown link like &lt;code&gt;![diagram](../../../../etc/passwd)&lt;/code&gt; or a custom instruction path to trick the runner into reading files outside the repository.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Major Feature Deep-Dives Since Part 1
&lt;/h2&gt;

&lt;p&gt;Now let's get into the really fun stuff! Here are the major architectural features we've engineered since publishing Part 1.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Multimodal Context Inspection, Visual PR Diffing &amp;amp; Screenshot Triage
&lt;/h3&gt;

&lt;p&gt;Until recently, AI code reviewers had a massive blind spot: &lt;strong&gt;they were completely blind to anything that wasn't plain text.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you updated an architecture diagram in &lt;code&gt;docs/architecture.png&lt;/code&gt;, tweaked a UI component screenshot, attached a PDF specification, or opened a GitHub Issue with a screenshot of a broken button, a text-only reviewer saw nothing.&lt;/p&gt;

&lt;p&gt;In our solution, we've unlocked Gemini's native multimodal superpowers across three distinct workflows:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7cg81xohnivkb7p99jh9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7cg81xohnivkb7p99jh9.png" alt="Multimodal Context &amp;amp; Visual PR Diffing Engine" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  A. Automatic Markdown Image &amp;amp; PDF Resolution
&lt;/h4&gt;

&lt;p&gt;Whenever a Markdown file (&lt;code&gt;README.md&lt;/code&gt;, &lt;code&gt;DESIGN.md&lt;/code&gt;, &lt;code&gt;ARCHITECTURE.md&lt;/code&gt;, or a blog post!) is included in the review context or modified in a PR diff, we scan the document for standard Markdown and HTML image references. We resolve the paths relative to the Markdown file, verify containment inside the repo, and attach the visual assets directly to the Gemini request. Now, when Gemini reviews your documentation updates, it actually &lt;strong&gt;looks at your architecture diagrams&lt;/strong&gt; to verify that the diagram matches your code and prose!&lt;/p&gt;

&lt;h4&gt;
  
  
  B. Side-by-Side Visual PR Diffing
&lt;/h4&gt;

&lt;p&gt;What happens when a PR modifies an existing architecture diagram, UI component snapshot, or application icon?&lt;/p&gt;

&lt;p&gt;Most AI reviewers either ignore modified images completely or summarise them in separate, isolated passes — which completely loses subtle visual regressions.&lt;/p&gt;

&lt;p&gt;Instead, our action retrieves &lt;strong&gt;both the "before" and "after" versions&lt;/strong&gt; of any modified graphic and passes them side-by-side into a single Gemini turn. Because both images sit together in the same multimodal attention window, Gemini performs direct visual diffing — spotting accidentally cropped text, resolution degradation, broken UI alignment, or missing arrows in an updated architecture diagram!&lt;/p&gt;

&lt;h4&gt;
  
  
  C. Multimodal Issue Triage for Remote Screenshots
&lt;/h4&gt;

&lt;p&gt;When users report bugs in GitHub Issues, they love pasting screenshots directly into the issue editor (which GitHub hosts at extensionless URLs like &lt;code&gt;https://github.com/user-attachments/assets/&amp;lt;uuid&amp;gt;&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;We upgraded our triage to extract remote HTTPS image URLs from both the issue body and discussion comments:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Safe Token Handling&lt;/strong&gt;: Images in private repositories require GitHub credentials to view. The downloader attaches your &lt;code&gt;GITHUB_TOKEN&lt;/code&gt; only to trusted GitHub domains — and strips it immediately if a link redirects to an external site.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Attack-Proof Downloads&lt;/strong&gt;: Because issue descriptions are untrusted user input, we block risky URLs (like internal network IPs or cloud metadata endpoints), cap downloads at 20 MB, and fall back cleanly to text triage if an image is missing or unreachable.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  D. Deterministic Image Downscaling (Saving Your Token Budget!)
&lt;/h4&gt;

&lt;p&gt;Here's a classic "gotcha" from production: high-resolution screenshots and uncompressed PNGs can easily top several megabytes each. Shoving dozens of multi-megabyte images into a review prompt is a recipe for pain. Review request latency can spike towards GitHub Action timeout thresholds, you risk slamming into API request limits, and you waste tokens on pixels that add no extra value to the review.&lt;/p&gt;

&lt;p&gt;To fix this, we added automated, deterministic downscaling using &lt;strong&gt;Pillow&lt;/strong&gt;. Any image (&lt;code&gt;.png&lt;/code&gt;, &lt;code&gt;.jpg&lt;/code&gt;, &lt;code&gt;.webp&lt;/code&gt;, &lt;code&gt;.gif&lt;/code&gt;) larger than &lt;strong&gt;600 KB&lt;/strong&gt; is compressed to a much smaller file size. Cool, right?&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Upgraded Default Model (&lt;code&gt;gemini-3.8-flash&lt;/code&gt;) &amp;amp; Thinking Budget Controls
&lt;/h3&gt;

&lt;p&gt;When I wrote Part 1, our default model was &lt;code&gt;gemini-3.6-flash&lt;/code&gt;. Since then, we upgraded through &lt;code&gt;gemini-3.7-flash&lt;/code&gt; and now default to &lt;strong&gt;&lt;code&gt;gemini-3.8-flash&lt;/code&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;We also introduced granular &lt;strong&gt;Reasoning &amp;amp; Thinking Budget Control&lt;/strong&gt; via the &lt;code&gt;thinking_level&lt;/code&gt; input:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Run Gemini Review Action&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;derailed-dash/gemini-review-action@v1&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;gemini_api_key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.GEMINI_API_KEY }}&lt;/span&gt;
          &lt;span class="na"&gt;github_token&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.GITHUB_TOKEN }}&lt;/span&gt;
          &lt;span class="na"&gt;thinking_level&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;low'&lt;/span&gt; &lt;span class="c1"&gt;# Options: low, medium, high, off, or integer budget (e.g. 2048)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;How thinking budgets work:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Dynamic by Default (Recommended for PRs)&lt;/strong&gt;: When omitted, Gemini runs in dynamic mode, automatically allocating reasoning tokens based on the complexity of your diff.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;FinOps Token Budget Limits (e.g. &lt;code&gt;low&lt;/code&gt; or &lt;code&gt;medium&lt;/code&gt;)&lt;/strong&gt;: Because thinking tokens are billed at the higher &lt;strong&gt;output token rate&lt;/strong&gt;, cost-conscious teams can cap the maximum reasoning headroom to ensure predictable per-review spending on massive diffs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Blazing Fast Issue Triage (&lt;code&gt;thinking_level: 'off'&lt;/code&gt;)&lt;/strong&gt;: When running in triage mode (&lt;code&gt;command: 'triage'&lt;/code&gt;), the model only needs to classify an issue and pick labels. Deep reasoning is complete overkill here. Setting &lt;code&gt;thinking_level: 'off'&lt;/code&gt; forces &lt;code&gt;thinking_budget=0&lt;/code&gt;, slashing triage latency to near-instant and cutting triage costs to fractions of a cent!&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. Smarter Sparse Mode: Bounded Dynamic Context Selection
&lt;/h3&gt;

&lt;p&gt;In Part 1, when a repository exceeded 1.5 MB (&lt;em&gt;Sparse Context Mode&lt;/em&gt;), the action attached the directory tree and static core files (&lt;code&gt;README.md&lt;/code&gt;, &lt;code&gt;pyproject.toml&lt;/code&gt;, etc.), and left it at that.&lt;/p&gt;

&lt;p&gt;But what if your PR modifies, say, &lt;code&gt;src/payments/stripe_webhook.py&lt;/code&gt; inside a 50 MB monorepo, but you also have relevant additional files in the repo, like &lt;code&gt;src/payments/models.py&lt;/code&gt; and &lt;code&gt;tests/payments/test_stripe.py&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqu96fp08zr3xzw2o7r0o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqu96fp08zr3xzw2o7r0o.png" alt="Monorepo Context &amp;amp; Self-Healing Engine" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To solve this, we introduced &lt;strong&gt;Bounded Dynamic Context Selection&lt;/strong&gt; (&lt;code&gt;gemini_review/context.py&lt;/code&gt; and &lt;code&gt;gemini_review/repo.py&lt;/code&gt;):&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Prioritised Rule Files &amp;amp; Core Context Budget Cap (&lt;code&gt;max_core_context_bytes&lt;/code&gt;)&lt;/strong&gt;: In Sparse Mode, the action loads your core project documents. But what if a repository has a 2 MB &lt;code&gt;README.md&lt;/code&gt; or dozens of markdown files? To prevent bulky documentation from blowing your token budget before code is even evaluated, we cap total core context at &lt;strong&gt;500 KB&lt;/strong&gt; and enforce strict intake ordering:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Agent rules take precedence&lt;/strong&gt;: Coding instructions and team guidelines (&lt;code&gt;AGENTS.md&lt;/code&gt;, &lt;code&gt;GEMINI.md&lt;/code&gt;, &lt;code&gt;CLAUDE.md&lt;/code&gt;, &lt;code&gt;.cursorrules&lt;/code&gt;) are prioritised at the very front of the queue so the reviewer always respects your project's rules.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Manifests &amp;amp; architecture next&lt;/strong&gt;: Core build manifests (&lt;code&gt;pyproject.toml&lt;/code&gt;, &lt;code&gt;package.json&lt;/code&gt;, &lt;code&gt;go.mod&lt;/code&gt;) and root docs (&lt;code&gt;README.md&lt;/code&gt;, &lt;code&gt;ARCHITECTURE.md&lt;/code&gt;) fill the remaining budget up to the 500 KB ceiling.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Two-Stage Dynamic Sister Context Selection&lt;/strong&gt;: In a 10,000-file monorepo, feeding every file path to an LLM wastes massive tokens before the review even starts. So we built a two-stage funnel:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Stage 1 (Deterministic Ranking)&lt;/strong&gt;: A Python ranker parses the PR diff for &lt;code&gt;import&lt;/code&gt; statements, directory proximity, and sister test/implementation filenames to bound the candidate pool to the top 500 files (&lt;code&gt;max_candidate_files&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stage 2 (4-Tier Architectural Selection)&lt;/strong&gt;: A fast, structured call to Gemini picks up to &lt;strong&gt;8 of the highest-value sister files&lt;/strong&gt; from that pool across four architectural tiers: &lt;em&gt;Tier 1&lt;/em&gt; (direct import dependencies and base classes), &lt;em&gt;Tier 2&lt;/em&gt; (sister unit tests, fixtures, and schemas), &lt;em&gt;Tier 3&lt;/em&gt; (domain precedents in sibling modules), and &lt;em&gt;Tier 4&lt;/em&gt; (shared utilities and configuration helpers).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Static Override (&lt;code&gt;extra_context_files&lt;/code&gt;)&lt;/strong&gt;: If you already know specific files you &lt;em&gt;always&lt;/em&gt; want attached alongside every review, you can pass &lt;code&gt;extra_context_files: 'src/core/security.py,docs/api-spec.pdf'&lt;/code&gt; and bypass the dynamic selector call entirely!&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  4. Extending Guardrails vs Replacing Prompts + Curated Skills Synchroniser
&lt;/h3&gt;

&lt;p&gt;Originally, if you wanted to add a single team rule — like &lt;em&gt;"All SQL queries must use parameterised inputs"&lt;/em&gt; — you had to copy the entire &lt;code&gt;.github/commands/gemini-review.toml&lt;/code&gt; file into your repo. The problem? As soon as you forked the base prompt into your repo, you missed out on all the upstream prompt engineering improvements we shipped in later versions (like our &lt;strong&gt;5-Axis Quality Evaluation Framework&lt;/strong&gt;)!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5curkf3mcx43o0wnqdg8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5curkf3mcx43o0wnqdg8.png" alt="AI Code Reviewer: Upgraded Intelligence Architecture with Skills &amp;amp; MCP" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The answer is to cleanly separate &lt;strong&gt;extending&lt;/strong&gt; instructions from &lt;strong&gt;replacing&lt;/strong&gt; them:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Extend (Recommended)&lt;/strong&gt;: Simply drop a Markdown file at &lt;code&gt;.github/review-instruction-additions.md&lt;/code&gt; in your repo, or pass inline rules via the &lt;code&gt;custom_instructions&lt;/code&gt; workflow input:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;      &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;custom_instructions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;- Ensure all database queries use parameterised inputs.&lt;/span&gt;
          &lt;span class="s"&gt;- Verify that new API endpoints include Pydantic request validation.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;The action keeps the full built-in 5-axis quality rubric, persona overlays, and schema rules, and cleanly appends your custom guardrails!&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Equip Custom Agent Skills (&lt;code&gt;.agents/skills/&lt;/code&gt;)&lt;/strong&gt;: Beyond simple markdown rules, you can mount full Agent Skills directly into your repository. The action automatically discovers skills placed in &lt;code&gt;.agents/skills/&lt;/code&gt; — whether they are custom coding guidelines, security checks, or official skills from the &lt;code&gt;google/skills&lt;/code&gt; catalog — and equips Gemini to enforce those exact domain practices during reviews.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bundled One-Command Installer Skill&lt;/strong&gt;: I had already created an agent skill called &lt;code&gt;install-gemini-code-review-action&lt;/code&gt;, in my &lt;a href="https://github.com/derailed-dash/dazbo-agent-skills" rel="noopener noreferrer"&gt;dazbo-agent-skills&lt;/a&gt; repo. Now, we also mirror this skill directly inside our reviewer repo. You can install the skill straight from the action repo:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx skills add derailed-dash/gemini-review-action &lt;span class="nt"&gt;-y&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; &lt;span class="nt"&gt;--skill&lt;/span&gt; install-gemini-code-review-action
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once installed, simply prompt your agent: &lt;strong&gt;"Set up Gemini code review in this repository."&lt;/strong&gt; The agent detects any existing workflows, interviews you on your preferred model, auth method (WIF vs API key), and persona, and generates the workflow files for you!&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Workflow Polish: Auto-Resolving Threads &amp;amp; Filtering Competing Bots
&lt;/h3&gt;

&lt;p&gt;Two of my favourite quality-of-life improvements came directly from real-world friction on busy pull requests:&lt;/p&gt;

&lt;h4&gt;
  
  
  A. Auto-Resolving Addressed Review Threads
&lt;/h4&gt;

&lt;p&gt;When you push a fix to a PR, the action re-examines prior review comments, confirms the issue has been resolved, and marks it fixed.&lt;/p&gt;

&lt;p&gt;However, if your repository enforces GitHub's &lt;strong&gt;"Require conversation resolution before merging"&lt;/strong&gt; rule, someone still has to manually click "Resolve conversation" on every single thread before you can merge — even though the bot already agreed you fixed it!&lt;/p&gt;

&lt;p&gt;With &lt;code&gt;resolve_addressed_threads: 'true'&lt;/code&gt;, the action automatically clicks "Resolve" on its own threads as soon as Gemini verifies the fix. It stays strictly in its lane: it only touches threads the bot created, never touches human comments, and gracefully warns you if your GitHub token needs additional permissions to resolve conversations.&lt;/p&gt;

&lt;h4&gt;
  
  
  B. Excluding Another Bot's Comments (&lt;code&gt;exclude_comment_authors&lt;/code&gt;)
&lt;/h4&gt;

&lt;p&gt;What happens if your team runs &lt;strong&gt;two&lt;/strong&gt; AI reviewers on the same repo (for instance, &lt;code&gt;claude[bot]&lt;/code&gt; alongside &lt;code&gt;gemini-review-action&lt;/code&gt;)?&lt;/p&gt;

&lt;p&gt;Because our action inspects existing PR comments to avoid repeating itself, it was picking up the other bot's review notes too. That meant Gemini ended up reading the other bot's homework and parroting the exact same points! You lost your independent second opinion, and you paid for hundreds of extra prompt tokens just to re-digest the other bot's prose.&lt;/p&gt;

&lt;p&gt;Adding &lt;code&gt;exclude_comment_authors: 'claude[bot]'&lt;/code&gt; filters out specified bots before building the prompt. Human feedback stays intact, and Gemini delivers a genuine, unbiased second opinion.&lt;/p&gt;




&lt;h2&gt;
  
  
  Battle-Hardened in Production: War Stories &amp;amp; Bug Fixes
&lt;/h2&gt;

&lt;p&gt;Here are a few real-world production bugs we hit since Part 1 — and how we engineered permanent fixes for them.&lt;/p&gt;

&lt;h3&gt;
  
  
  War Story 1: The Generated Schema That Blew the Token Budget
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The Problem&lt;/strong&gt;: A pull request touching 30 files crashed without posting a review, failing with a token limit error. The culprit? A tiny 4 KB diff buried inside a 2.9 MB auto-generated &lt;code&gt;openapi.json&lt;/code&gt; file. Because our prompt builder attached the entire current content of every modified file alongside its diff, that single generated file consumed the entire Gemini token window on its own!&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Fix&lt;/strong&gt;: Rather than playing whack-a-mole adding filenames to an ignore list, we capped all attached source files at &lt;strong&gt;128 KB&lt;/strong&gt; with a clean truncation marker (diff patches themselves are never capped). If a massive prompt still approaches the model's budget, the action gracefully sheds peripheral repo context first, ensuring the core diff review always succeeds.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  War Story 2: GitHub's Concurrency Trap (and How Our Bot Caught It)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The Problem&lt;/strong&gt;: If a developer pushes three commits in quick succession, you don't want to pay Gemini to review all three. We added a standard GitHub Actions &lt;code&gt;concurrency&lt;/code&gt; block with &lt;code&gt;cancel-in-progress: true&lt;/code&gt; to kill redundant runs. But we hit a snag: whenever someone left an ordinary comment on the PR, GitHub cancelled the running review! Workflow-level concurrency evaluates before the job filters kick in, treating any comment as a new run.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Caught by Our Own Bot&lt;/strong&gt;: We tried tweaking the concurrency key, but when we opened the pull request, &lt;strong&gt;our own Gemini Review Action reviewed it and pointed out our fix created a new race condition in the opposite direction!&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Fix&lt;/strong&gt;: Moving &lt;code&gt;concurrency&lt;/code&gt; down to the &lt;strong&gt;job level&lt;/strong&gt; ensures GitHub only cancels runs for actual review triggers on the same PR:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;review&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;concurrency&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;group&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;gemini-review-${{ github.event.pull_request.number || github.event.issue.number }}&lt;/span&gt;
      &lt;span class="na"&gt;cancel-in-progress&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  War Story 3: Making "Commit Suggestion" Actually Work
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The Problem&lt;/strong&gt;: Developers love clicking GitHub's &lt;strong&gt;"Commit suggestion"&lt;/strong&gt; button directly from an inline review comment. But LLMs are notorious for trimming leading whitespace or getting multiline replacement ranges slightly wrong — meaning a one-click commit can easily botch your indentation or overwrite the wrong lines.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Fix&lt;/strong&gt;: Before posting an inline suggestion, we run a deterministic sanitiser over it. It matches the source file lines, restores stripped indentation, and corrects any off-by-one replacement ranges. When a developer clicks that button, the resulting commit is clean, properly indented, and builds first time.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  War Story 4: Surviving Transient GitHub Outages
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The Problem&lt;/strong&gt;: During an incident where the GitHub API threw intermittent &lt;code&gt;503 Service Unavailable&lt;/code&gt; errors, the action successfully generated reviews from Gemini, only to crash when posting them to GitHub. We’d paid for the tokens, but the reviews were lost into the ether.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Fix&lt;/strong&gt;: We wrapped all GitHub comment and review posting in an exponential backoff retry. A review you've already paid for is never thrown away over a temporary API hiccup.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;Looking back at how far &lt;a href="https://github.com/derailed-dash/gemini-review-action" rel="noopener noreferrer"&gt;&lt;strong&gt;Gemini PR Review &amp;amp; Triage Action&lt;/strong&gt;&lt;/a&gt; has come since that first weekend build in July, I'm genuinely blown away. What started as an emergency lifeboat after the sunsetting of &lt;code&gt;run-gemini-cli&lt;/code&gt; has grown into a comprehensive, multimodal, enterprise-grade engineering harness.&lt;/p&gt;

&lt;p&gt;Whether you're a solo hobbyist who wants Emperor Palpatine or Rick Sanchez roasting your Python diffs for $0.02 a pop, or an Enterprise Cloud Architect rolling out keyless WIF authentication, BigQuery billing attribution, and architectural guardrails across hundreds of corporate repositories — this action is built for you:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7tp30f6fu03eudqgrm7v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7tp30f6fu03eudqgrm7v.png" alt="Rick Sanchez Persona Review Output" width="799" height="573"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Beyond CI/CD: Bringing Gemini Review into Your Agentic Loops
&lt;/h3&gt;

&lt;p&gt;While we designed this action primarily to automate GitHub pull request reviews, the modular architecture we've engineered under &lt;code&gt;gemini_review/&lt;/code&gt; unlocks an exciting new frontier: &lt;strong&gt;inner-loop agent verification&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In my recent deep dive, &lt;a href="https://dev.to/gde/loop-engineering-in-the-harness-autonomous-self-correcting-systems-part-2-155e"&gt;&lt;strong&gt;Loop Engineering in the Harness: Autonomous, Self-Correcting Systems&lt;/strong&gt;&lt;/a&gt;, I explored how reliable agentic architectures rely on tight, deterministic feedback loops (Generate → Verify → Correct → Converge) to eliminate hallucinated code and regressions before human intervention.&lt;/p&gt;

&lt;p&gt;Because &lt;code&gt;gemini_review&lt;/code&gt; is structured as a standalone, lightweight Python package executable via &lt;code&gt;uv&lt;/code&gt;, you don't have to wait for a remote CI push to run it. You can wire the review engine directly into your local development harness as a pre-commit or pre-push verification step. Your local coding agent can execute a local review pass against its own unstaged git diff, parse the structured severity findings, and self-correct regressions with zero session bias — before anyone else ever inspects the code!&lt;/p&gt;

&lt;h2&gt;
  
  
  Install It!
&lt;/h2&gt;

&lt;p&gt;If you haven't tried it yet (or if you installed &lt;code&gt;v1.1&lt;/code&gt; back in July and haven't looked at the new inputs since!), now is the perfect time to upgrade:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Equip your AI agent in seconds&lt;/strong&gt;, then prompt it: &lt;em&gt;"Set up Gemini code review in this repo"&lt;/em&gt;:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx skills add derailed-dash/gemini-review-action &lt;span class="nt"&gt;-y&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; &lt;span class="nt"&gt;--skill&lt;/span&gt; install-gemini-code-review-action
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Or grab the starter workflows&lt;/strong&gt; directly from &lt;a href="https://github.com/derailed-dash/gemini-review-action" rel="noopener noreferrer"&gt;derailed-dash/gemini-review-action&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Give the repository a star ⭐ on GitHub&lt;/strong&gt; — it massively helps others discover the project, and it helps me too!&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let me know in the comments how you get on, what persona you're running in your pipelines, and what features you'd love to see next!&lt;/p&gt;




&lt;h2&gt;
  
  
  Before You Go
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Please share&lt;/strong&gt; 📢 this with anyone that you think will be interested. It might help them, and it really helps me!&lt;/li&gt;
&lt;li&gt;Please &lt;strong&gt;leave a reaction or comment&lt;/strong&gt; 💬. Interaction is good!&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Add a star&lt;/strong&gt; ⭐ on my repos!&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Follow&lt;/strong&gt; 👉 and &lt;strong&gt;subscribe&lt;/strong&gt; 🔔, so you don’t miss my content.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  References and Useful Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.to/gde/automated-github-code-reviews-using-google-gemini-4l0f"&gt;Part 1: Automated GitHub Code Reviews Using Google Gemini (Dev.to)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/google-cloud/automated-github-code-reviewsusing-google-gemini-7b4d027b3092" rel="noopener noreferrer"&gt;Part 1: Automated GitHub Code Reviews Using Google Gemini (Medium)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/derailed-dash/gemini-review-action" rel="noopener noreferrer"&gt;Dazbo’s Gemini PR Review &amp;amp; Triage Action (GitHub Repository)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/marketplace/actions/dazbo-s-gemini-code-review-issue-triage" rel="noopener noreferrer"&gt;Dazbo’s Gemini PR Review &amp;amp; Triage Action (GitHub Marketplace)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/derailed-dash/dazbo-agent-skills" rel="noopener noreferrer"&gt;Dazbo’s Agent Skills Repository (dazbo-agent-skills)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://aistudio.google.com/?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;Google AI Studio&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://cloud.google.com/iam/docs/workload-identity-federation-with-deployment-pipelines?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;Google Cloud Workload Identity Federation with GitHub Actions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://cloud.google.com/vertex-ai/generative-ai/pricing?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;Google Cloud Vertex AI Generative AI Pricing&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://antigravity.google/?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;Google Antigravity&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/gde/from-vibing-chaos-to-reliable-agents-the-what-why-and-how-of-harness-engineering-4ba0"&gt;Beyond Vibe Coding: From Vibing Chaos to Reliable Agents — Harness Engineering Part 1&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/gde/loop-engineering-in-the-harness-autonomous-self-correcting-systems-part-2-155e"&gt;Beyond Vibe Coding: Loop Engineering in the Harness — Autonomous, Self-Correcting Systems (Part 2)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dazbo.co.uk/" rel="noopener noreferrer"&gt;Dazbo’s Portfolio&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>githubactions</category>
      <category>pullrequest</category>
      <category>cicdpipeline</category>
      <category>googlegemini</category>
    </item>
    <item>
      <title>Loop Engineering in the Harness: Autonomous, Self-Correcting Systems</title>
      <dc:creator>Darren "Dazbo" Lester</dc:creator>
      <pubDate>Mon, 12 Oct 2026 21:36:09 +0000</pubDate>
      <link>https://dev.to/gde/loop-engineering-in-the-harness-autonomous-self-correcting-systems-part-2-155e</link>
      <guid>https://dev.to/gde/loop-engineering-in-the-harness-autonomous-self-correcting-systems-part-2-155e</guid>
      <description>&lt;p&gt;You are in &lt;strong&gt;Part 2&lt;/strong&gt; of the series &lt;strong&gt;&lt;em&gt;"Beyond Vibe Coding: The Engineering Blueprint for Reliable AI Agents"&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;h3&gt;
  
  
  🗺️ The Series Roadmap: Beyond Vibe Coding
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;In 2026, software development is drowning in fragmented buzzwords: Harness Engineering, Loop Engineering, Context Engineering, Spec-Driven Development, Evaluators, and Sandboxes. Are they competing frameworks? Redundant prompt techniques? Or something fundamentally new?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This four-part series unifies these concepts into a single, cohesive architectural blueprint for building software with AI without writing code manually:&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Part 1:&lt;/strong&gt; &lt;a href="https://dev.to/gde/from-vibing-chaos-to-reliable-agents-the-what-why-and-how-of-harness-engineering-4ba0"&gt;&lt;strong&gt;From Vibing Chaos to Reliable Agents: The What, Why, and How of Harness Engineering&lt;/strong&gt;&lt;/a&gt;
We diagnose the hangover of vibe coding, unpack the paradigm shift of &lt;em&gt;shifting developer interventions left&lt;/em&gt;, establish our bedrock formula (&lt;strong&gt;Agent = Model + Harness&lt;/strong&gt;), explore the Lewis Hamilton motorsport analogy, and deconstruct the deterministic components that make up a production developer environment.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Part 2: Loop Engineering in the Harness: Autonomous, Self-Correcting Systems (This Article)&lt;/strong&gt;
We fire up the dynamic runtime engine of the harness: deconstructing the core loop components, establishing hybrid evaluation rubrics (deterministic tests + LLM goal fidelity + tool trajectory verification), and applying the Ratchet Principle.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Part 3: Spec-Driven Development For-the-Win: Disposable Code, Living Blueprints, and Building Like a Boss (Coming Soon)&lt;/strong&gt;
We explore Spec-Driven Development (where code is disposable and specifications are the single source of truth), master Google Antigravity's unified harness and interactive slash commands (&lt;code&gt;/grill-me&lt;/code&gt;, &lt;code&gt;/plan&lt;/code&gt;, &lt;code&gt;/goal&lt;/code&gt;, &lt;code&gt;/boost&lt;/code&gt;, &lt;code&gt;/learn&lt;/code&gt;), and combine formal specs with tactical workflows via the 4-Phase Hybrid Power Pattern.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Part 4: Scaling the Harness: Practical Loop Patterns, ADK 2 Graphs, Recursive Harness², and Harness Maintenance (Coming Soon)&lt;/strong&gt;
We bring everything together with practical loop patterns you can wire into any repo (from declarative Markdown and &lt;code&gt;loopy&lt;/code&gt; to Google ADK 2 graphs), keep context clean across iterations with short-lived subagents, explore Google Research's recursive Harness² framework, and cover ongoing harness maintenance.&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  The "Generate and Fix" Trap: Stop Being the Human Correction Loop
&lt;/h2&gt;

&lt;p&gt;Howdy friends, and welcome back!&lt;/p&gt;

&lt;p&gt;In &lt;a href="https://dev.to/gde/from-vibing-chaos-to-reliable-agents-the-what-why-and-how-of-harness-engineering-4ba0"&gt;Part 1&lt;/a&gt;, we established the bedrock formula of modern agentic engineering:&lt;/p&gt;

&lt;p&gt;

&lt;/p&gt;
&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord text"&gt;&lt;span class="mord"&gt;Agent&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord text"&gt;&lt;span class="mord"&gt;Model&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;+&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord text"&gt;&lt;span class="mord"&gt;Harness&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;We deconstructed the core deterministic components of the harness: hierarchical context rules (&lt;code&gt;AGENTS.md&lt;/code&gt; / &lt;code&gt;GEMINI.md&lt;/code&gt;), living version-controlled state, curated Model Context Protocol (MCP) tools, on-demand skills, sandboxing, and observability. This is how we engineered the race car chassis.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;But wait... How does the work actually get done?&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In simple, naive AI interactions, developers issue a prompt, get some output, and then typically course-correct. Maybe the developer copies the output from the terminal into the chat and asks for a fix.&lt;/p&gt;

&lt;p&gt;Notice what is happening here: we have an &lt;strong&gt;iterative cycle of action, verification, and course-correction&lt;/strong&gt;. You cannot escape it. But in an ad-hoc vibe coding workflow, &lt;strong&gt;you are the loop&lt;/strong&gt;. You act as an exhausted organic clipboard, forcing yourself to micromanage, inspect, and babysit every single turn. If you're doing that, you haven't automated much; you're just paying a subscription to watch a terminal like a nervous ferret.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fx0b7bhu5ssxbe7f1mvrz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fx0b7bhu5ssxbe7f1mvrz.png" alt="Watching the agent like a nervous ferret" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Loop Engineering&lt;/strong&gt; automates that execution cycle.&lt;/p&gt;

&lt;p&gt;Instead of forcing a human to watch and correct every turn, the loop enables our agent to cycle through action, verification, and course-correction &lt;strong&gt;autonomously within the harness&lt;/strong&gt;. The agent executes the code, runs the automated test suites, evaluates its work against strict rubrics, refines its hypotheses, and makes corrections... On its own!&lt;/p&gt;

&lt;p&gt;Crucially, this does not mean ejecting the human entirely. It means moving from continuous babysitting to strategic governance: &lt;strong&gt;Human-in-the-Loop does NOT mean Human-in-Every-Turn&lt;/strong&gt;. The agent executes the rapid, deterministic feedback cycle autonomously, and only pauses to escalate to the human conductor at &lt;strong&gt;predefined escalation points&lt;/strong&gt; — such as hitting persistent evaluation plateaus, encountering ambiguous requirements, or proposing irreversible, high-risk actions.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F97g5hpnm9bcqw6wtnwot.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F97g5hpnm9bcqw6wtnwot.png" alt="The Loop" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;A Crucial Distinction: The Development Workbench, Not Runtime Infrastructure&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When we talk about loop engineering, the goal is not usually to ship autonomous, self-modifying while-loops into a live, customer-facing production application. The value of harness engineering and loop engineering is that it provides a disciplined feedback mechanism during the development phase to &lt;strong&gt;build software that is production-grade&lt;/strong&gt;. The loop is the automated forge where code is hammered, tested, and tempered; what you actually deploy to the cloud is resilient, production-ready software.&lt;/p&gt;

&lt;p&gt;In tokenomics terms, this aligns to so-called &lt;strong&gt;Spec Spend&lt;/strong&gt; (as explored in my upcoming enterprise whitepaper, &lt;em&gt;The Agentic Revolution&lt;/em&gt;). Burning tokens in the developer harness to explore hypotheses, run tests, and self-correct is a &lt;strong&gt;high-value, high-leverage investment&lt;/strong&gt;. Spending a couple of dollars in developer Spec Spend to forge a hardened application prevents catastrophic regressions and uncontrollable costs in production &lt;strong&gt;Run Spend&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Core Components of an Engineered Developer Loop
&lt;/h2&gt;

&lt;p&gt;To move beyond fragile trial-and-error, an engineered agentic loop requires distinct, interconnected components:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhwkl5yfre9dls5ociokg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhwkl5yfre9dls5ociokg.png" alt="Core Components of the Loop" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1 — Goal (The Anchor):&lt;/strong&gt; A clear, unambiguous statement of what the agent must accomplish. In long-running autonomous runs, context compression can cause the model to drift. &lt;strong&gt;A resilient harness restates the core goal on every single iteration&lt;/strong&gt;, keeping the agent firmly anchored to its original objective.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2 — Context (The Environment &amp;amp; Grounding Data):&lt;/strong&gt; Everything the agent knows about the world before taking an action. This context extends far beyond prompt templates; it is the total information environment available to the loop:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Standing Architectural Rules &amp;amp; Guardrails:&lt;/strong&gt; Hierarchical instructions, coding standards, and operational boundaries drawn from &lt;code&gt;GEMINI.md&lt;/code&gt;, &lt;code&gt;AGENTS.md&lt;/code&gt;, and activated Agent Skills.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Workspace Data &amp;amp; Local Fixtures:&lt;/strong&gt; Source code, schema files, seed datasets, sample payloads, and test mocks residing directly in the repository.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dynamic Knowledge &amp;amp; Database State:&lt;/strong&gt; Grounding information retrieved on demand via MCP tools or APIs, such as querying living documentation from (say) Confluence or Google Drive, inspecting issues on GitHub, or introspecting schemas and retrieving data from databases.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 &lt;strong&gt;Decoupling Engineering Guardrails from Application Specs&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A crucial architectural discipline in production harnesses is separating the &lt;strong&gt;Application Goal Specification&lt;/strong&gt; from the &lt;strong&gt;Engineering Discipline&lt;/strong&gt;. Naive prompt engineering often conflates the two, burying feature requirements beneath paragraphs of repetitive coding hygiene instructions. In reality, engineering guardrails (e.g. Python standards, mandating TDD approaches, Pydantic input parameterisation) should be &lt;strong&gt;independent of any single application spec&lt;/strong&gt;. They represent reusable, global, organisation-, domain- or team-level engineering policies.&lt;/p&gt;

&lt;p&gt;Centralising them in persistent workspace configurations (&lt;code&gt;GEMINI.md&lt;/code&gt;, &lt;code&gt;AGENTS.md&lt;/code&gt;) and reusable Agent Skills means you define them once and govern them centrally across all projects. The feature specification stays lean and domain-focused.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;3 — Tools (The Levers):&lt;/strong&gt; The restricted set of actions the agent is permitted to execute, including sandboxed shell commands and MCP server tools. The harness strictly limits tool access to reduce blast radius and limit tool choice paralysis.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4 — Evals (The Objective Judge):&lt;/strong&gt; The scoring mechanisms that evaluate the progress of each iteration. Without automated evals, the agent is flying blind. A robust harness evaluates across three dimensions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Deterministic Output Checks:&lt;/strong&gt; Mechanical unit tests, integration suites, and static linters (&lt;code&gt;pytest&lt;/code&gt;, &lt;code&gt;ruff&lt;/code&gt;, &lt;code&gt;codespell&lt;/code&gt;) that verify the compilation, syntax, and functional correctness of the generated artifacts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tool Trajectory &amp;amp; Process Verification:&lt;/strong&gt; Inspecting &lt;em&gt;how&lt;/em&gt; the agent reached the result. Did it invoke only approved tools in the expected sequence? Did it respect tool schemas without hallucinating arguments? Did it avoid thrashing loops or calling forbidden APIs?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Semantic LLM-as-a-Judge Analyses:&lt;/strong&gt; Using models to evaluate the qualitative requirements — crucially including &lt;strong&gt;Goal Fidelity&lt;/strong&gt; (verifying whether the solution actually delivers what was requested) and architectural cleanliness. While semantic autoraters can use rubric scales or qualitative feedback, framing them as &lt;strong&gt;binary &lt;code&gt;yes/no&lt;/code&gt; assertions&lt;/strong&gt; is often a very effective approach to eliminate subjective score drift.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;5 — Memory (Loop History &amp;amp; Scratchpad):&lt;/strong&gt; The structured log of what has been attempted across preceding iterations. The agent records what worked, what failed, and the progression of evaluation scores over time. In a well-engineered harness, this persistent scratchpad prevents the model from repeating known dead-ends or thrashing in circular loops.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6 — Iteration Discipline (The One-Change Rule):&lt;/strong&gt; This is about applying the scientific method to autonomous iteration. This discipline applies specifically to changes evaluated for &lt;strong&gt;semantic value&lt;/strong&gt;. When iterating against semantic autoraters, the loop instructs the agent to &lt;strong&gt;modify one thing at a time&lt;/strong&gt; before re-scoring. If multiple semantic changes are introduced at once, causal observability collapses: if a rubric score drops, the agent cannot tell which alteration caused the regression. Conversely, purely mechanical deterministic fixes (resolving compiler syntax, fixing lint warnings from &lt;code&gt;ruff&lt;/code&gt; or &lt;code&gt;codespell&lt;/code&gt;, and formatting) can and should be batch-remediated in a single turn.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;7 — Escalation Protocol (The Safety Valve):&lt;/strong&gt; Explicit operational triggers that halt the loop and request human intervention. For example, if an agent encounters conflicting specifications, hits three consecutive evaluation failures, or proposes an irreversible action (e.g. deleting cloud infrastructure), it must not hallucinate a guess. It must package its findings, present a reasoned recommendation, and yield control to the human conductor.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;8 — Stopping Condition (The Finish Line):&lt;/strong&gt; Clear, programmatic exit criteria that tell the loop when execution is complete. Such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;100% of deterministic checks and semantic rubric assertions passing with zero lint warnings.&lt;/li&gt;
&lt;li&gt;Target state verification: the critique model explicitly certifies that the initial goal has been fully met.&lt;/li&gt;
&lt;li&gt;A convergence plateau where successive iterations produce negligible score improvements.&lt;/li&gt;
&lt;li&gt;Hard circuit breakers, such as reaching a maximum iteration count (e.g. 5 loops) or a predefined token spend limit.&lt;/li&gt;
&lt;/ul&gt;




&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Is It a Loop Bug or a Harness Bug?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When an autonomous agent goes off the rails during development, we often waste days trying to fix the wrong things.&lt;/p&gt;

&lt;p&gt;Use this simple litmus test:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;If you can resolve the issue by refining the prompt, sharpening the goal, updating the rubric, or adjusting the stopping condition → It is a Loop bug.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;If resolving the issue requires changing tool definitions, adjusting sandbox permissions, modifying execution timeouts, or intercepting runtime errors → It is a Harness bug.&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Don't attempt to solve a harness problem by writing a more pleading prompt. Fix the layer that actually broke!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2wl702450gdl9ykkwedg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2wl702450gdl9ykkwedg.png" alt="Loop bug vs harness bug" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The Ratchet Principle: Engineering Continuous Improvement
&lt;/h3&gt;

&lt;p&gt;What happens once you diagnose an edge case or failure that &lt;em&gt;wasn't&lt;/em&gt; caught by your initial harness?&lt;/p&gt;

&lt;p&gt;This brings us to the operational crown jewel of harness engineering: &lt;strong&gt;The Ratchet Principle&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbmkd3fxr8kuyps54f3kw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbmkd3fxr8kuyps54f3kw.png" alt="Ratchet Principle" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When an AI agent stumbles, makes an architectural mistake, or introduces a subtle bug, the amateur response is to re-prompt the model in the chat: &lt;em&gt;"No, don't do that, use the new API method instead."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;That is an utter waste of a lesson. The moment that conversation ends, that context evaporates into thin air. In tomorrow's session, on a new branch, or when a teammate runs a similar task, the agent will walk directly into the exact same trap.&lt;/p&gt;

&lt;p&gt;Under the Ratchet Principle:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Whenever an agent makes a mistake, you update the harness, not just the prompt.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Did the agent use an outdated API parameter?&lt;/strong&gt; Update the workspace &lt;code&gt;GEMINI.md&lt;/code&gt; or add an authoritative type schema.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Did the agent forget to handle a specific error code?&lt;/strong&gt; Add a permanent check to the binary evaluation rubric.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Did the agent create an unformatted commit?&lt;/strong&gt; Add a pre-commit hook to your Git harness.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Did the agent struggle with a Google Cloud product?&lt;/strong&gt; Load the corresponding skill from the &lt;code&gt;google-cloud-developer&lt;/code&gt; plugin.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Like a mechanical ratchet, every single failure permanently tightens the system. The harness clicks forward one notch. Once a rule or rubric check is committed to your repository, that specific failure mode is eliminated forever. Over time, your development harness becomes an impenetrable repository of institutional engineering wisdom.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Loops Work: The Power of Feedback
&lt;/h2&gt;

&lt;p&gt;Why go through the effort of building a multi-component loop instead of relying on a single, well-crafted prompt?&lt;/p&gt;

&lt;p&gt;I created an application that demonstrates building an application agentically, and compares &lt;em&gt;with and without&lt;/em&gt; harness and loop, side-by-side.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fu31wyplsqe93fpa59d8c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fu31wyplsqe93fpa59d8c.png" alt="Side-by-side harness engineering demo" width="800" height="507"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We'll deep-dive into this shortly. But for now, I'll give you the key findings from this application, which align with industry findings. Essentially, if you have a harness with a loop, these are the outcomes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;You use &lt;strong&gt;fewer tokens.&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;overall time&lt;/strong&gt; to get to a solution is &lt;strong&gt;dramatically reduced&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;human input&lt;/strong&gt; required is &lt;strong&gt;massively reduced&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;overall cost&lt;/strong&gt; to produce the solution is &lt;strong&gt;significantly reduced&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;quality&lt;/strong&gt; of your solution, and its alignment to your requirements, is much better.&lt;/li&gt;
&lt;li&gt;Most importantly — &lt;strong&gt;the solution is more likely to &lt;em&gt;actually work&lt;/em&gt;.&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;TL;DR — single-pass prompting is gambling that an LLM will get dozens of interconnected variables right on the first try.&lt;/p&gt;

&lt;p&gt;In contrast, wrapping the model in an automated loop mirrors the exact rhythm experienced software engineers use every day: propose a targeted change, run the tests and evals, feed the diagnostics straight back into the next turn, and iterate until the solution passes. The loop keeps the model honest, converges on working code dramatically faster, and stops intermediate errors from compounding into an unrecoverable mess.&lt;/p&gt;

&lt;h3&gt;
  
  
  Three Traps to Avoid
&lt;/h3&gt;

&lt;p&gt;However, naive loops without rigorous harness constraints may fall prey to some common &lt;strong&gt;loop traps&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1 — The Premature Exit:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The agent runs superficial tests, assumes everything works because there were no syntax errors, and prematurely declares victory.&lt;br&gt;&lt;br&gt;
&lt;em&gt;Neutralised by: Mandatory TDD gates and non-negotiable passing thresholds on automated test suites.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2 — The Sycophantic Yes-Agent:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We all know that LLMs can be hopelessly sycophantic.&lt;br&gt;&lt;br&gt;
&lt;em&gt;Q: "Do I look good in this shell suit?"&lt;/em&gt;&lt;br&gt;&lt;br&gt;
&lt;em&gt;A: "Why yes, Dazbo! You look so hunky wearing that."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjs7amlxly7y0alilx5cb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjs7amlxly7y0alilx5cb.png" alt="Do I look good in this shell suit?" width="768" height="1231"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When using an LLM to rate the output of a loop, the model easily falls into the same trap — uncritically praising the worker agent's output.&lt;br&gt;&lt;br&gt;
&lt;em&gt;Neutralised by: Structuring evaluations as strict, binary assertions and verifiable code artifacts.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3 — The Bottomless Cash Pit:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;An unachievable rubric threshold or a brittle stopping condition traps the agent in a recursive loop, repeatedly modifying the same file and burning through hundred-dollar token budgets without making forward progress. While developer Spec Spend is meant to be exploratory, an unconstrained loop turns healthy investment into an uncontrolled financial bonfire.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkb74pduwgb8op3ndlake.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkb74pduwgb8op3ndlake.png" alt="Uncontrolled token burn" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Neutralised by: Stall detection, plateau convergence checks, and hard iteration circuit breakers.&lt;/em&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  The Hybrid Evaluation Rubric (Deterministic + Semantic)
&lt;/h2&gt;

&lt;p&gt;One of the biggest mistakes teams make when building agent loops is relying on fluffy, subjective evaluation prompts: &lt;em&gt;"Rate the quality of this code on a scale of 1 to 5."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Models are notoriously inconsistent when asked for qualitative ratings; what scores a 4 on Tuesday might score a 2 on Wednesday. In contrast, &lt;strong&gt;binary rubrics&lt;/strong&gt; convert these fluffy judgments into repeatable deterministic results. So let's just turn the evaluations into verifiable &lt;code&gt;yes/no&lt;/code&gt; questions!&lt;/p&gt;

&lt;p&gt;Furthermore, as Google AI leaders like Shubham Saboo have pointed out in &lt;em&gt;Finally, Loop Engineering Explained&lt;/em&gt; when contrasting loops with traditional prompt engineering, reliable loops must &lt;strong&gt;automate what is checkable&lt;/strong&gt; — and that begins with &lt;strong&gt;testing whether the generated output actually achieves the goal that was set&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/ew6gBJNzC5w" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;The goal is not just passing unit tests and being clean of linting errors. We also need to be sure that the solution actually delivers the feature requested.&lt;/p&gt;

&lt;p&gt;For this reason, our evaluation rubric should combine &lt;strong&gt;deterministic checks&lt;/strong&gt; with &lt;strong&gt;semantic checks&lt;/strong&gt;. The semantic checks are executed by a critique agent or LLM-as-a-judge autorater.&lt;/p&gt;

&lt;p&gt;And we must evaluate &lt;strong&gt;tool trajectory&lt;/strong&gt; alongside code execution. You cannot evaluate only the final artifact; the harness must verify &lt;em&gt;how&lt;/em&gt; the agent reached the result. Tool trajectory evaluation operates across two complementary layers:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Deterministic Trajectory Evaluation (Mechanical Trace Inspection):&lt;/strong&gt; Code-level validation inspecting the execution trace without using an LLM. Did the agent invoke only authorised tools from its allowlist? Did arguments strictly satisfy JSON parameter schemas? Did it follow mandatory prerequisite ordering (e.g. running the test suite &lt;em&gt;before&lt;/em&gt; attempting to commit code)? Did it stay within maximum tool call budgets rather than entering an unconstrained loop?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Semantic Trajectory Evaluation (Reasoning &amp;amp; Efficiency):&lt;/strong&gt; Evaluated by a critique agent or LLM judge. Did the agent select the &lt;em&gt;most appropriate and efficient&lt;/em&gt; tool for the problem, or did it take an absurdly convoluted detour (e.g. running fifteen individual file-read calls instead of a single targeted grep)? When a tool returned an unexpected error or empty result, did the agent reason soundly about the failure and adapt its strategy, or did it flail repetitively?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;An agent that arrives at a working file after making ten redundant, unapproved tool calls or taking dangerous exploratory detours is an operational failure.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjf5xpj23l770udijg7bq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjf5xpj23l770udijg7bq.png" alt="Two Tier Evaluation Rubrics" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The Anatomy of a Production-Grade Evaluation Rubric
&lt;/h3&gt;

&lt;p&gt;Here is a simple example; a 10-check rubric illustrating how deterministic and semantic checks — across both code and tool trajectories — work together:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gh"&gt;# Evaluation Rubric&lt;/span&gt;

&lt;span class="gu"&gt;## Part A: Deterministic &amp;amp; Static Checks (Automated via Test Runners, Linters &amp;amp; Trace Inspectors)&lt;/span&gt;

| ID | Check (1 = True, 0 = False) | Evaluation Method | Result |
|:---|:---|:---|:---:|
| 1.1 | All unit tests in &lt;span class="sb"&gt;`tests`&lt;/span&gt; pass cleanly? | &lt;span class="sb"&gt;`pytest`&lt;/span&gt; runner | [ ] |
| 1.2 | &lt;span class="sb"&gt;`uvx ruff check .`&lt;/span&gt; and &lt;span class="sb"&gt;`uvx codespell`&lt;/span&gt; report zero errors or warnings? | Static analysis CLI | [ ] |
| 1.3 | Function signatures use PEP 585 standard type hints (e.g. &lt;span class="sb"&gt;`list[str]`&lt;/span&gt;, &lt;span class="sb"&gt;`dict[str, Any]`&lt;/span&gt;)? | Linter | [ ] |
| 1.4 | All database queries use parameterised inputs (no raw f-strings or string concatenation)? | Static analysis / AST | [ ] |
| 1.5 | &lt;span class="gs"&gt;**Deterministic Trajectory Conformance:**&lt;/span&gt; Did the agent invoke only authorised tools, satisfy parameter schemas, respect tool call limits, and follow mandatory prerequisite ordering (e.g. test before commit)? | Harness Trace Inspector (Code) | [ ] |

&lt;span class="gu"&gt;## Part B: Semantic Yes/No Analyses (Evaluated via LLM-as-a-Judge / Critique Agent)&lt;/span&gt;

| ID | Binary Semantic Assertion (1 = True, 0 = False) | Evaluation Method | Result |
|:---|:---|:---|:---:|
| 2.1 | &lt;span class="gs"&gt;**Target State Completion (Goal Fidelity):**&lt;/span&gt; Does the generated solution demonstrably deliver all functional capabilities and explicit deliverables declared in the goal statement, without omitting mandatory acceptance criteria? | Semantic Judge | [ ] |
| 2.2 | &lt;span class="gs"&gt;**Scope Discipline (Anti-Hallucination):**&lt;/span&gt; Does the solution achieve the goal without generating unrequested speculative abstractions, hallucinating unused helper modules, or modifying files outside the agreed boundary? | Semantic Judge | [ ] |
| 2.3 | &lt;span class="gs"&gt;**Trajectory Efficiency &amp;amp; Tool Reasoning:**&lt;/span&gt; Did the agent choose sensible, direct tool pathways to solve the problem rather than taking convoluted detours or repeatedly retrying failed tool strategies without adaptation? | Semantic Judge | [ ] |
| 2.4 | &lt;span class="gs"&gt;**Architectural Integrity &amp;amp; Interface Boundaries:**&lt;/span&gt; Does the code maintain clean boundaries, preventing internal database implementation details or raw connection strings from leaking into public interfaces or caller errors? | Semantic Judge | [ ] |
| 2.5 | &lt;span class="gs"&gt;**Design Rationale &amp;amp; Intent:**&lt;/span&gt; Does the module-level docstring clearly explain the architectural &lt;span class="ge"&gt;*why*&lt;/span&gt; (why this pattern was chosen over alternatives) rather than merely restating what the code does? | Semantic Judge | [ ] |

&lt;span class="gs"&gt;**Passing Criteria:**&lt;/span&gt; 10 / 10 (100% pass required before code can be committed).
&lt;span class="gs"&gt;**Iteration Policy:**&lt;/span&gt; Failures on code, test suites, or sub-optimal tool trajectories feed diagnostic feedback into the next turn for autonomous remediation.
&lt;span class="gs"&gt;**Hard Stop (Human Escalation):**&lt;/span&gt; The harness only aborts and alerts the developer if the agent breaches security boundaries (e.g. unapproved destructive commands), enters an unrecoverable tool thrashing loop, or reaches the maximum iteration limit (5 loops).
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice how this structure enforces discipline across every dimension:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Checks 1.1–1.5&lt;/strong&gt; verify mechanical hygiene (syntax, compilation, test passage, and deterministic tool trajectory allowlists/orderings).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Checks 2.1–2.2&lt;/strong&gt; verify &lt;strong&gt;Goal Fidelity&lt;/strong&gt; — comparing the candidate output directly against the initial user intent. If the agent forgot batch processing or wandered off into speculative refactoring, Check 2.1 or 2.2 drops to 0, and the loop refuses to exit.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Check 2.3&lt;/strong&gt; verifies semantic tool trajectory efficiency — ensuring the agent didn't burn tokens on irrational intermediate actions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Checks 2.4–2.5&lt;/strong&gt; verify semantic architecture, error safety, and living documentation quality.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By presenting the agent with this exact markdown rubric, the model can self-score its work after every turn. It doesn't wonder whether its output is "good enough"; it knows with precision whether it satisfied the criteria and achieved the goal.&lt;/p&gt;

&lt;h4&gt;
  
  
  No Arbitrary Point Ceiling
&lt;/h4&gt;

&lt;p&gt;While our example shows 10 checks for clear illustration, let's avoid any misconceptions: &lt;strong&gt;an evaluation rubric does not have an arbitrary 10-point ceiling&lt;/strong&gt;. In practice, your rubric can have whatever point total you want. For example, you might also include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Frontend contract checks:&lt;/strong&gt; Verifying TypeScript interface alignment, component contracts, and state store mutations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;API wiring verification:&lt;/strong&gt; Confirming route registration, middleware attachment, payload serialisation, and HTTP status code mappings.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Latency bounds:&lt;/strong&gt; Asserting that mock or integration calls stay strictly within defined latency budgets (e.g. 95% in under 250ms).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security invariants:&lt;/strong&gt; Enforcing parameterised queries, sanitised inputs, absence of leaked credentials or stack traces, and zero-trust egress policies.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Side-by-Side Demo: The Harness Engineering Workbench
&lt;/h2&gt;

&lt;p&gt;Theory is cheap. Let's prove it!&lt;/p&gt;

&lt;p&gt;To demonstrate the quantifiable difference between raw vibe coding and disciplined loop engineering, I built an open-source, interactive, split-screen evaluation workbench: the &lt;a href="https://github.com/derailed-dash/harness-engineering-demo" rel="noopener noreferrer"&gt;Harness Engineering Demo&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4yxtl767xywq1u8isyrq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4yxtl767xywq1u8isyrq.png" alt="Harness Engineering Workbench" width="800" height="330"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The workbench pits two autonomous tracks against each other in real time, each running concurrently with the same model. (The demo uses &lt;code&gt;Gemini 3.8-Flash&lt;/code&gt; out-of-the-box, but this is configurable.)&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;The Unharnessed Track — Vibe Coding:&lt;/strong&gt; A raw single prompt containing the user specification is dispatched directly to the model. We supply no additional workspace rules or guardrails, and no specialised skills. There is no autonomous loop and no iterative self-healing. We evaluate the output once, at the very end.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Harnessed Track — Loop Engineering:&lt;/strong&gt; An autonomous multi-turn loop executes in an isolated workspace. We provide the &lt;em&gt;same specification prompt&lt;/em&gt; as before. But this time we also provide additional context and guardrails, we equip the agent with relevant skills, and we evaluate each iteration with a 14-point rubric.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;em&gt;What is the demo actually building?&lt;/em&gt; Well, the specification is for the non-trivial task of building a &lt;em&gt;"Cosmic Trivia &amp;amp; Strategy Conquest Game"&lt;/em&gt;, a full-stack sci-fi game featuring a FastAPI backend, a directed graph of galactic sectors, turn-based combat, dynamic AI trivia generation, and an interactive browser-based star map with real-time HUD metrics and combat dialogues.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Harness: Context, Skills, and Living Memory
&lt;/h3&gt;

&lt;p&gt;Let's start by looking at the supporting &lt;strong&gt;context&lt;/strong&gt; we supply (&lt;code&gt;harness/harness_context.md&lt;/code&gt;). This would typically be part of your global reusable context (e.g. &lt;code&gt;AGENTS.md&lt;/code&gt; or &lt;code&gt;GEMINI.md&lt;/code&gt;) that you use as an engineer, as a team, or even as an organisation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gh"&gt;# Engineering Context &amp;amp; Harness Guardrails&lt;/span&gt;

&lt;span class="gu"&gt;## Persona &amp;amp; Role&lt;/span&gt;

You are a Principal Software Engineer and Systems Architect. You produce modular, production-grade, and self-documenting code following strict engineering standards. You practice test-driven development, enforce strict interface contracts, and design systems with clear separation of concerns.

&lt;span class="gu"&gt;## 1. Environment &amp;amp; Coding Standards&lt;/span&gt;
&lt;span class="p"&gt;
-&lt;/span&gt; &lt;span class="gs"&gt;**Python Version**&lt;/span&gt;: Python 3.13 standard.
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**Type Hinting**&lt;/span&gt;: Strict PEP 585 (use built-in &lt;span class="sb"&gt;`list[str]`&lt;/span&gt;, &lt;span class="sb"&gt;`dict[str, Any]`&lt;/span&gt;, &lt;span class="sb"&gt;`tuple[int, ...]`&lt;/span&gt;, never use deprecated &lt;span class="sb"&gt;`typing.List`&lt;/span&gt; or &lt;span class="sb"&gt;`typing.Dict`&lt;/span&gt;).
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**Scope Discipline**&lt;/span&gt;: Only create required files specified in the task goal or architecture. Do not generate speculative helper files, hallucinated third-party dependencies, or dead code.

&lt;span class="gu"&gt;## 2. Test-Driven Development (TDD)&lt;/span&gt;
&lt;span class="p"&gt;
-&lt;/span&gt; &lt;span class="gs"&gt;**Mandatory Test Suite**&lt;/span&gt;: Author a comprehensive unit test suite in &lt;span class="sb"&gt;`tests/`&lt;/span&gt; before or alongside implementation covering core domain logic, edge cases, and state transitions.
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**Verification Gate**&lt;/span&gt;: Verify that all unit tests pass cleanly via &lt;span class="sb"&gt;`pytest`&lt;/span&gt; before declaring any task complete.

&lt;span class="gu"&gt;## 3. Backend Architecture &amp;amp; Security Guardrails&lt;/span&gt;
&lt;span class="p"&gt;
-&lt;/span&gt; &lt;span class="gs"&gt;**Parameterisation**&lt;/span&gt;: All API request bodies and input parameters must use structured Pydantic models with input validation. Never accept raw unvalidated dictionaries or execute dynamic evaluation (&lt;span class="sb"&gt;`eval`&lt;/span&gt;, &lt;span class="sb"&gt;`exec`&lt;/span&gt;).
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**Error Handling**&lt;/span&gt;: Invalid inputs, illegal state transitions, or domain rule violations must trigger actionable HTTP 400 responses without leaking internal stack traces.
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**Architectural Integrity**&lt;/span&gt;: Maintain strict modular boundaries. Keep domain logic pure and independent of HTTP transports, database drivers, or UI presentation. Expose REST endpoints with explicit routing.
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**Documentation**&lt;/span&gt;: Include clear top-of-module docstrings explaining architectural intent and design rationale ('why' over 'what').

&lt;span class="gu"&gt;## 4. Autonomous Harness Workflow &amp;amp; Tooling Protocol&lt;/span&gt;
&lt;span class="p"&gt;
-&lt;/span&gt; &lt;span class="gs"&gt;**On-Demand Skill Discovery &amp;amp; Activation**&lt;/span&gt;: Inspect the &lt;span class="sb"&gt;`&amp;lt;available_skills&amp;gt;`&lt;/span&gt; catalogue in your harness context; when &lt;span class="sb"&gt;`# ACTIVATED ENGINEERING SKILLS`&lt;/span&gt; is already loaded in your context, apply those skills directly without re-activating them.
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**Initial Turn Synthesis (Iteration 1)**&lt;/span&gt;: Respond directly in Markdown with a concise &lt;span class="gs"&gt;**Architectural &amp;amp; TDD Verification Plan**&lt;/span&gt; (150–250 words) detailing module boundaries, Pydantic request/response schemas, and the core unit test cases (&lt;span class="sb"&gt;`tests/`&lt;/span&gt;), concluding with a single brief (~15-line) Python code block illustrating the core Pydantic request/response contracts (omit full multi-file implementations).
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**Automated Gate Verification**&lt;/span&gt;: At the end of each iteration turn, your generated deliverables are materialised into the workspace and the harness evaluation gate executes &lt;span class="sb"&gt;`pytest`&lt;/span&gt;, &lt;span class="sb"&gt;`ruff`&lt;/span&gt;, and all mechanical and semantic rubric checks, recording a structured &lt;span class="gs"&gt;**Iteration Evidence Receipt**&lt;/span&gt; in &lt;span class="sb"&gt;`LIVING_MEMORY.md`&lt;/span&gt;.
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**Targeted Self-Healing from Living Memory (Iteration 2+)**&lt;/span&gt;: When living memory diagnostics from a prior iteration are present in your context, respond directly in Markdown with a concise &lt;span class="gs"&gt;**Self-Healing Remediation Summary**&lt;/span&gt; (100–200 words) citing each failed check ID, its root cause, and the targeted code fix applied.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note how this additional context defines the engineering persona, enforces our coding standards, mandates test-driven development (TDD), describes error handling requirements, captures how we want code documentation written, and establishes the autonomous loop workflow.&lt;/p&gt;

&lt;p&gt;Also, because we want output of each loop to guide the next efficiently, this particular loop instructs the agent &lt;strong&gt;not to dump full multi-file implementations into the conversational stream&lt;/strong&gt;. Instead it asks for a succinct summary of waht went wrong and how we might remediate next time.&lt;/p&gt;

&lt;p&gt;Crucially, this is all &lt;em&gt;reusable, project-agnostic&lt;/em&gt; context rather than context coupled to the application specification.&lt;/p&gt;

&lt;p&gt;Next, observe that the harness has a number of &lt;strong&gt;specialised skills&lt;/strong&gt; available in &lt;code&gt;harness/skills/&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;api-and-interface-design&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;gemini-api-dev&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;test-driven-development&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Rather than hardcoding these skill names into &lt;code&gt;harness_context.md&lt;/code&gt; or pre-loading every skill's full Markdown instructions into the startup prompt, the harness dynamically scans the &lt;code&gt;SKILL.md&lt;/code&gt; YAML frontmatter (&lt;code&gt;name&lt;/code&gt; and &lt;code&gt;description&lt;/code&gt;) in &lt;code&gt;harness/skills/&lt;/code&gt; and injects a lightweight &lt;code&gt;&amp;lt;available_skills&amp;gt;&lt;/code&gt; catalog. The agent inspects this catalog against the specification and invokes &lt;code&gt;activate_skill&lt;/code&gt; on demand to load only the instructions it needs.&lt;/p&gt;

&lt;p&gt;Finally, our harness maintains &lt;strong&gt;living memory&lt;/strong&gt;: a persistent feedback ledger stored at &lt;code&gt;harness/output/LIVING_MEMORY.md&lt;/code&gt;. When an iteration fails, the exact rubric diagnostics, failed check IDs, and remediation hints are recorded to &lt;code&gt;LIVING_MEMORY.md&lt;/code&gt; and reinjected into the next turn's prompt alongside the original specification. This is what enables surgical self-healing rather than blind guessing.&lt;/p&gt;

&lt;h3&gt;
  
  
  Under the Hood: Orchestrating the Loop with Google ADK
&lt;/h3&gt;

&lt;p&gt;To ensure a fair, apples-to-apples comparison, both tracks in the workbench are executed through the &lt;strong&gt;Google Agent Development Kit (&lt;code&gt;google-adk&lt;/code&gt;)&lt;/strong&gt; using &lt;code&gt;Runner&lt;/code&gt; and &lt;code&gt;InMemorySessionService&lt;/code&gt;. This isolates the impact of the &lt;strong&gt;Harness&lt;/strong&gt; rather than comparing different SDK runtimes:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvhrjjt4wrg9qcs1whw25.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvhrjjt4wrg9qcs1whw25.png" alt="Google ADK Harness Architecture" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Track 1 — Unharnessed (&lt;code&gt;app/agents/unharnessed.py&lt;/code&gt;):&lt;/strong&gt; Runs a bare ADK &lt;code&gt;Agent(instruction="", tools=[])&lt;/code&gt; in a single pass. It receives only the raw specification from &lt;code&gt;specs/cosmic_conquest_spec.md&lt;/code&gt; with no persona, no skills, and no verification tools.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Track 2 — Harnessed (&lt;code&gt;app/agents/agent.py&lt;/code&gt; &amp;amp; &lt;code&gt;app/agents/harnessed.py&lt;/code&gt;):&lt;/strong&gt; Separates pure ADK agent definitions (&lt;code&gt;agent.py&lt;/code&gt;, compatible with &lt;code&gt;adk web&lt;/code&gt;, &lt;code&gt;adk run&lt;/code&gt;, and &lt;code&gt;adk eval&lt;/code&gt;) from the SSE runner (&lt;code&gt;harnessed.py&lt;/code&gt;), orchestrating an ADK &lt;code&gt;LoopAgent(max_iterations=5)&lt;/code&gt; composed of two sub-agents operating over shared session state (&lt;code&gt;session.state&lt;/code&gt;):

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Builder &lt;code&gt;LlmAgent&lt;/code&gt; (&lt;code&gt;harnessed_builder_agent&lt;/code&gt;):&lt;/strong&gt; Equipped with our &lt;code&gt;harness_context.md&lt;/code&gt;, the &lt;code&gt;&amp;lt;available_skills&amp;gt;&lt;/code&gt; catalogue, five session-scoped ADK &lt;code&gt;FunctionTool&lt;/code&gt;s (&lt;code&gt;activate_skill&lt;/code&gt;, &lt;code&gt;write_workspace_file&lt;/code&gt;, &lt;code&gt;read_workspace_file&lt;/code&gt;, &lt;code&gt;run_pytest&lt;/code&gt;, &lt;code&gt;run_ruff_check&lt;/code&gt;), and an &lt;code&gt;after_agent_callback&lt;/code&gt; (&lt;code&gt;materialise_builder_output_callback&lt;/code&gt;) that materialises generated files into the isolated workspace. Each tool operates on &lt;code&gt;tool_context.state["workspace_path"]&lt;/code&gt;, injects activated skills into &lt;code&gt;tool_context.state["skills_context"]&lt;/code&gt;, and appends deterministic audit entries to &lt;code&gt;tool_context.state["tool_trajectory"]&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Custom Gate Agent (&lt;code&gt;RubricEvaluationGateAgent(BaseAgent)&lt;/code&gt;):&lt;/strong&gt; A pure evaluation and escalation gate that executes &lt;code&gt;pytest&lt;/code&gt; and &lt;code&gt;ruff&lt;/code&gt;, runs the 14-point rubric evaluator (loading semantic criteria declaratively from &lt;code&gt;harness/RUBRIC.md&lt;/code&gt;), persists diagnostics to &lt;code&gt;LIVING_MEMORY.md&lt;/code&gt;, and yields &lt;code&gt;EventActions(escalate=should_escalate, state_delta=...)&lt;/code&gt;. When &lt;code&gt;escalate=True&lt;/code&gt; is emitted (on a 14/14 pass or plateau), the parent ADK &lt;code&gt;LoopAgent&lt;/code&gt; terminates cleanly; otherwise, the updated &lt;code&gt;living_memory_feedback&lt;/code&gt; state flows automatically into the builder agent's next iteration.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Programmatic Exit Conditions &amp;amp; Circuit Breakers
&lt;/h3&gt;

&lt;p&gt;In autonomous loop engineering, you must never allow an agent to loop indefinitely or guess when it has finished. The workbench's &lt;code&gt;RubricEvaluationGateAgent&lt;/code&gt; enforces three strict programmatic exit conditions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Target Gate Pass (Clean Exit)&lt;/strong&gt;: To eliminate subjective "good enough" assessments, the workbench implements a rigorous, two-tier 14-point rubric schema. We will exit the loop upon achieving a flawless &lt;strong&gt;14 / 14 (100%)&lt;/strong&gt; rubric score across all deterministic and semantic checks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hard Iteration Cap (Spend Circuit Breaker)&lt;/strong&gt;: A hard limit of &lt;strong&gt;5 iterations&lt;/strong&gt; (&lt;code&gt;MAX_ITERATIONS = 5&lt;/code&gt;). If the agent cannot satisfy all checks within five turns, execution halts immediately to prevent runaway token spend.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Convergence Plateau (Stall Detection)&lt;/strong&gt;: If the rubric score fails to improve across &lt;strong&gt;3 consecutive turns&lt;/strong&gt; (&lt;code&gt;PLATEAU_LIMIT = 3&lt;/code&gt;), the loop aborts early rather than thrashing in circular remediation attempts.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here is the exact production rubric configured in our workbench:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gh"&gt;# Production Evaluation Rubric: Cosmic Conquest&lt;/span&gt;

&lt;span class="gu"&gt;## Tier 1: Deterministic Mechanical Sensors (8.0 Points)&lt;/span&gt;

| ID | Category | Check | Evaluation Method |
|:---|:---|:---|:---|
| 1.1 | Deterministic | Unit Tests Passage | &lt;span class="sb"&gt;`pytest`&lt;/span&gt; runner |
| 1.2 | Deterministic | Static Analysis (Ruff) | &lt;span class="sb"&gt;`ruff check .`&lt;/span&gt; |
| 1.3 | Deterministic | PEP 585 Type Hints | AST Inspector (&lt;span class="sb"&gt;`list[str]`&lt;/span&gt;, &lt;span class="sb"&gt;`dict[str, Any]`&lt;/span&gt;) |
| 1.4 | Deterministic | Parameterised Input Safety | AST Inspector (&lt;span class="sb"&gt;`eval()`&lt;/span&gt;, &lt;span class="sb"&gt;`exec()`&lt;/span&gt;) |
| 1.5 | Deterministic | Deterministic Tool Trajectory | Harness Trace Inspector |
| 1.6 | Deterministic | Interactive Frontend Client Structure | HTML &amp;amp; DOM Inspector (&lt;span class="sb"&gt;`#shields`&lt;/span&gt;, &lt;span class="sb"&gt;`#energy`&lt;/span&gt;, combat modal) |
| 1.7 | Deterministic | Frontend Interactive API Wiring | AST / Script Inspector (fetch bindings to &lt;span class="sb"&gt;`/api/game/attack`&lt;/span&gt;, &lt;span class="sb"&gt;`answer`&lt;/span&gt;, &lt;span class="sb"&gt;`state`&lt;/span&gt;) |
| 1.8 | Deterministic | Dynamic API Contract &amp;amp; Progression Topology | Dynamic TestClient Boot (FastAPI startup &amp;amp; valid progression targets) |

&lt;span class="gu"&gt;## Tier 2: Semantic Goal Fidelity &amp;amp; Ergonomics (6.0 Points)&lt;/span&gt;

| ID | Check | Evaluation Method | Weight |
|:---|:---|:---|:---:|
| 2.1 | Semantic | Target State Completion (Goal Fidelity) | Gemini LLM-as-a-Judge |
| 2.2 | Semantic | Scope Discipline (Anti-Hallucination) | Gemini LLM-as-a-Judge |
| 2.3 | Semantic | Architectural Integrity | Gemini LLM-as-a-Judge |
| 2.4 | Semantic | Error &amp;amp; Remediation Clarity | Gemini LLM-as-a-Judge |
| 2.5 | Semantic | Design Rationale &amp;amp; Intent | Gemini LLM-as-a-Judge |
| 2.6 | Semantic | Progression Ergonomics &amp;amp; Interactivity | Explicit single-action sector card/tile affordance inspector |

Passing Bar: 14 / 14 (Non-negotiable 100% threshold)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Head-to-Head Verdict
&lt;/h3&gt;

&lt;p&gt;If you run the side-by-side comparison multiple times, you'll find the following:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Unharnessed (Vibing)&lt;/th&gt;
&lt;th&gt;Harnessed Track (Loop)&lt;/th&gt;
&lt;th&gt;Operational Advantage of Harness / Loop&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Execution Duration&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Typically 1.5–2+ minutes&lt;/td&gt;
&lt;td&gt;Typically 23–35s&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;3–4x faster&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Combined Tokens&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Typically 18,000–45,000&lt;/td&gt;
&lt;td&gt;~6,600–6,900 (&lt;code&gt;~900–1,100&lt;/code&gt; out)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;~75–85% fewer tokens (~15x fewer output tokens)&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Estimated Cost&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;~$0.010–$0.017&lt;/td&gt;
&lt;td&gt;~$0.0014–$0.0015&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;~85% cheaper (~7–8x lower cost)&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Rubric Score&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Between 6–11 / 14 (Always fails)&lt;/td&gt;
&lt;td&gt;14 / 14 (Always passes)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Reliable 100% success rate&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Functional Outcome&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;❌ Broken / Non-functional&lt;/td&gt;
&lt;td&gt;✅ Fully playable &amp;amp; verified&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Only harnessed code works&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Here are the side-by-side metrics from one run, captured directly from this live evaluation workbench:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F31buroq234mlsc3nn4np.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F31buroq234mlsc3nn4np.png" alt="Harness Workbench Side-by-Side Metrics: Unharnessed (Single Pass) (33,129 tokens, $0.0122, 2:03, 11.0/14.0 FAIL) vs Harnessed Autonomous Loop (24,192 tokens, $0.0066, 0:31, 14.0/14.0 PASS)" width="799" height="299"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can watch a full live demonstration of the solution here:&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/7pKl2SvmPuU" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(You can inspect the full workbench codebase, explore the evaluation engine, or run the live demo locally — and because the ADK &lt;code&gt;LoopAgent&lt;/code&gt;, &lt;code&gt;RubricEvaluationGateAgent&lt;/code&gt;, and &lt;code&gt;FunctionTool&lt;/code&gt; suite in &lt;code&gt;app/agents/&lt;/code&gt; are completely project-agnostic, the repository README includes a 4-step guide for lifting this exact ADK harness blueprint into your own Python projects. Clone the open-source repository at &lt;a href="https://github.com/derailed-dash/harness-engineering-demo" rel="noopener noreferrer"&gt;derailed-dash/harness-engineering-demo&lt;/a&gt;.)&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Unpacking the Results: Why the Harnessed Loop Dominates
&lt;/h3&gt;

&lt;p&gt;These numbers might appear counter-intuitive at first glance. Why would an iterative multi-turn loop be &lt;strong&gt;three to four times faster&lt;/strong&gt; and &lt;strong&gt;~85% cheaper&lt;/strong&gt; than a single-turn prompt?&lt;/p&gt;

&lt;p&gt;Let's break down these results:&lt;/p&gt;

&lt;h4&gt;
  
  
  1. Only the Harnessed Version Actually Works
&lt;/h4&gt;

&lt;p&gt;The most sobering lesson of the comparison is functional: &lt;strong&gt;the vibe-coded solution is almost always non-functional&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;On paper, the unharnessed agent produced a directory of plausible-looking files. It wrote Python classes and generated a colourful HTML file. But when loaded into a browser, the game was completely dead. The sector tiles lacked click event bindings, the combat modal was un-wired, and several FastAPI endpoints failed to resolve dynamic path parameters correctly.&lt;/p&gt;

&lt;p&gt;It typically scores between 6 and 11 out of 14, failing key mechanical checks and progression requirements.&lt;/p&gt;

&lt;p&gt;In contrast, the harnessed agent's code reliably achieves a flawless 14 / 14. Because these checks include interrogating the frontend DOM structure and API bindings, we can be reasonably confident that the resulting game actually plays.&lt;/p&gt;

&lt;h4&gt;
  
  
  2. Much Faster: The Paradox of Disciplined Bursts
&lt;/h4&gt;

&lt;p&gt;Intuition suggests that a single-turn prompt should be faster than an iterative loop. The workbench proves the exact opposite: &lt;strong&gt;the harnessed loop usually finishes in 24 to 35 seconds, whilst the unharnessed run invariably drags on for 1.5 to 2+ minutes.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Why? Two architectural factors work together here:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Disciplined Output vs Speculative Rambling:&lt;/strong&gt; When an unguided model is asked to build a full application in a single pass without constraints, it falls into speculative rambling. It attempts to stream 15,000–17,000+ output tokens in one continuous burst — generating repetitive boilerplate, guessing at auxiliary classes, and second-guessing its own structure mid-stream. The harnessed agent, by contrast, is guided by &lt;code&gt;harness/harness_context.md&lt;/code&gt; and activated skills to operate in compact, high-signal bursts: Turn 1 synthesises a concise &lt;strong&gt;Architectural &amp;amp; TDD Verification Plan&lt;/strong&gt; (&lt;code&gt;~800&lt;/code&gt; output tokens, scoring &lt;code&gt;12.0 / 14.0&lt;/code&gt; out of the gate) while &lt;code&gt;materialise_builder_output_callback&lt;/code&gt; materialises the modular workspace files, and Turn 2 emits a focused &lt;strong&gt;Self-Healing Remediation Summary&lt;/strong&gt; (&lt;code&gt;~240&lt;/code&gt; output tokens) to close the remaining &lt;code&gt;+2.0&lt;/code&gt; gap (&lt;code&gt;12.0 -&amp;gt; 14.0&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Externalised Loop Reasoning (&lt;code&gt;ThinkingLevel.LOW&lt;/code&gt;):&lt;/strong&gt; Rather than burning 30+ seconds per turn in unconstrained internal chain-of-thought pondering (&lt;code&gt;thinking_budget&lt;/code&gt; is deprecated on Gemini 3.x+, so we configure &lt;code&gt;ThinkingConfig(thinking_level=ThinkingLevel.LOW)&lt;/code&gt; on &lt;code&gt;gemini-3.8-flash&lt;/code&gt;), the harnessed builder agent externalises its iterative reasoning into the deterministic ADK &lt;code&gt;LoopAgent&lt;/code&gt;, the &lt;code&gt;RubricEvaluationGateAgent&lt;/code&gt;, and &lt;code&gt;LIVING_MEMORY.md&lt;/code&gt;. On Turn 1, it writes clean, minimal scaffolding and unit tests in seconds. The rubric gate runs locally in milliseconds, highlights any exact delta, and Turn 2 applies a surgical update. Fast generation paired with real compiler, test, and linter feedback consistently beats slow, unverified internal pondering.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  3. Higher Efficiency: Eliminating Waste and Output Cost
&lt;/h4&gt;

&lt;p&gt;The cost breakdown reveals an equally striking reality: &lt;strong&gt;the loop is typically around one-seventh to one-eighth of the cost (~$0.0015 vs ~$0.011–$0.012+, consuming ~6,600–6,900 tokens vs 26,000–30,000+ tokens) of the unharnessed single prompt&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Without context guardrails, the unharnessed model repeatedly duplicated schema definitions, wrote inline mock trivia data spanning hundreds of lines, and generated unrequested helper utilities that were never imported.&lt;/p&gt;

&lt;p&gt;The harness prevents this bloat in three ways:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;harness_context.md&lt;/code&gt; explicitly enforces architectural boundaries (e.g. modular separation between the game engine and the trivia service).&lt;/li&gt;
&lt;li&gt;The rubric's &lt;strong&gt;Scope Discipline (Check 2.2)&lt;/strong&gt; actively penalises extraneous abstractions. Because the agent knows it will be graded on tight adherence to scope, it writes concise, well-factored code rather than padding its output with defensive speculative fluff.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Context Pruning Across Iterations:&lt;/strong&gt; Rather than carrying the entire raw Turn 1 conversation history into Turn 2, the ADK builder agent prunes prior-turn chat history and receives only the distilled &lt;strong&gt;Iteration Evidence Receipt&lt;/strong&gt; from &lt;code&gt;LIVING_MEMORY.md&lt;/code&gt; (containing the score delta, &lt;code&gt;pytest&lt;/code&gt;/&lt;code&gt;ruff&lt;/code&gt; verification status, active failures, and next-turn remediation targets).&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  4. Resilience To Model Changes
&lt;/h4&gt;

&lt;p&gt;Finally, there is an overarching architectural benefit that transcends any individual run: &lt;strong&gt;resilience against model updates&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;When teams rely on raw vibe coding, their production pipeline is fundamentally fragile. A prompt that works reasonably well on a Tuesday afternoon can suddenly fail on Wednesday when the provider deploys a minor model update, alters default temperature behaviour, or updates safety guardrails. When your only quality assurance is the model's raw generative mood, you have no baseline.&lt;/p&gt;

&lt;p&gt;A robust harness decouples and insulates us from changes to the model. The harness provides the immutable invariant rails: deterministic unit test runners, static analysers, type checkers, and semantic rubric gates. If a newer, smaller, or faster model stumbles on its initial attempt, the harness catches the defect instantly and guides autonomous remediation. You stop relying on model perfection and start relying on systemic verification.&lt;/p&gt;




&lt;h2&gt;
  
  
  Off-the-Shelf Loop Mastery: The Loop Library and the &lt;code&gt;loopy&lt;/code&gt; Skill
&lt;/h2&gt;

&lt;p&gt;Designing an effective developer loop from scratch can initially feel daunting. How do you calibrate the stopping conditions? How do you prevent an agent from running amok while refactoring a legacy codebase?&lt;/p&gt;

&lt;p&gt;The good news is: &lt;strong&gt;you don't have to invent every loop pattern from first principles.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The agentic engineering community has begun codifying battle-tested loops into open-source catalogs. The preeminent reference in this space is &lt;a href="https://signals.forwardfuture.com/loop-library/" rel="noopener noreferrer"&gt;The Loop Library&lt;/a&gt; by Forward Future, accompanied by the open-source &lt;a href="https://github.com/Forward-Future/loopy/tree/main/skills/loopy" rel="noopener noreferrer"&gt;&lt;code&gt;loopy&lt;/code&gt; agent skill&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F309b3eg6wsar4f9p1lc7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F309b3eg6wsar4f9p1lc7.png" alt="The Loop Library" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  What is The Loop Library?
&lt;/h3&gt;

&lt;p&gt;The Loop Library treats AI agent loops as &lt;strong&gt;bounded feedback systems with non-negotiable terminal states&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Every published loop in the library adheres to a rigorous architectural contract:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;The Ready-to-Use Prompt:&lt;/strong&gt; An unambiguous, declarative instruction that defines what the agent must do on each iteration.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Verify / Stop Criteria:&lt;/strong&gt; Explicit, measurable terminal conditions (such as green CI or full test suite passage) that tell the loop when to stop.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Strict Authority Boundaries:&lt;/strong&gt; Clear operational tripwires separating read actions, code modifications, and irreversible operations (e.g. merging to main or releasing to production).&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  The &lt;code&gt;loopy&lt;/code&gt; Agent Skill: Your In-IDE "Loop Doctor"
&lt;/h3&gt;

&lt;p&gt;Rather than manually browsing a website, you can install the &lt;strong&gt;&lt;code&gt;loopy&lt;/code&gt; skill&lt;/strong&gt; directly into your developer harness (such as Google Antigravity). When equipped with &lt;code&gt;loopy&lt;/code&gt;, your agent becomes an intelligent loop architect:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Find &amp;amp; Adapt:&lt;/strong&gt; Ask your agent: &lt;em&gt;"Find a loop in the Loop Library to help me speed up my test suite."&lt;/em&gt; The agent queries the catalog, identifies the nearest matching pattern, and adapts its thresholds to your specific stack.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Audit Existing Loops ("Loop Doctor"):&lt;/strong&gt; Before letting an agent loose on a long-running task, ask &lt;code&gt;loopy&lt;/code&gt; to audit your prompt. It inspects your instructions for weak checks, missing stopping conditions, or unbounded authority, hardening the loop before a single token is burned.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Craft via Guided Interview:&lt;/strong&gt; If no existing pattern fits your problem, &lt;code&gt;loopy&lt;/code&gt; initiates a structured interview, probing you on the desired outcome, permitted tools, and exact success criteria to craft a bespoke, bounded loop.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Save to &lt;code&gt;LOOPS.md&lt;/code&gt;:&lt;/strong&gt; Once a loop proves effective in your repository, &lt;code&gt;loopy&lt;/code&gt; can commit it directly into a version-controlled &lt;code&gt;LOOPS.md&lt;/code&gt; file in the root of your project. This transforms successful loop patterns into shared, institutional team muscle memory.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Real-World Loop Patterns You Can Run Today
&lt;/h3&gt;

&lt;p&gt;Here are a few very cool, practical examples from &lt;a href="https://signals.forwardfuture.com/loop-library/" rel="noopener noreferrer"&gt;The Loop Library&lt;/a&gt; that illustrate how loop engineering transforms daily developer operations:&lt;/p&gt;

&lt;h4&gt;
  
  
  1. The Code Housekeeper Loop
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The Problem:&lt;/strong&gt; Technical debt, unformatted files, dead code, and low-priority linter warnings accumulate across repositories because human developers rarely have the time or patience to clean them up manually.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;How It Works:&lt;/strong&gt; As defined in the &lt;a href="https://signals.forwardfuture.com/loop-library/loops/housekeeper-loop/" rel="noopener noreferrer"&gt;Code Housekeeper Loop&lt;/a&gt;, the agent wakes up, scans the codebase for static analysis warnings or dead imports, selects &lt;strong&gt;one single discrete issue&lt;/strong&gt;, applies a targeted fix, runs the full test suite to prove zero regressions, and commits the change.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stopping Condition:&lt;/strong&gt; Stops cleanly when all linter warnings are cleared or when a predefined maximum iteration cap is reached. Because it modifies only one file per turn, blast radius is completely contained.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  2. The Fresh Clone Loop
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The Problem:&lt;/strong&gt; A developer clones a repository, attempts to run the setup script, and immediately hits missing environment variables, unpinned dependency conflicts, or outdated documentation. "Works on my machine" strikes again.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;How It Works:&lt;/strong&gt; The &lt;a href="https://signals.forwardfuture.com/loop-library/loops/fresh-clone-loop/" rel="noopener noreferrer"&gt;Fresh Clone Loop&lt;/a&gt; simulates the day-one developer experience in an isolated sandbox. It performs a completely clean clone, executes the documented bootstrap scripts, installs dependencies from scratch, and runs the initial test suite. If an installation step fails, it diagnoses the missing prerequisite, updates the &lt;code&gt;setup.sh&lt;/code&gt; script or &lt;code&gt;README.md&lt;/code&gt;, wipes the sandbox, and retries.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stopping Condition:&lt;/strong&gt; The loop halts only when a fresh clone successfully builds, boots, and passes tests from an empty state without human assistance.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  3. The Test Suite Speed Loop
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The Problem:&lt;/strong&gt; Over time, test suites bloat. Slow database fixtures, redundant sleep calls, and un-parallelised test cases drag local feedback loops from thirty seconds to fifteen minutes, destroying developer velocity.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;How It Works:&lt;/strong&gt; The &lt;a href="https://signals.forwardfuture.com/loop-library/loops/test-suite-speed-loop/" rel="noopener noreferrer"&gt;Test Suite Speed Loop&lt;/a&gt; profiles test execution times, identifies the slowest test files, isolates bottlenecks (such as redundant network calls or unmocked I/O), refactors the slowest test case, and verifies that the entire suite still passes with identical assertions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stopping Condition:&lt;/strong&gt; Halts when overall test suite execution time drops below a declared target threshold (e.g. under 60 seconds) with 100% test passage.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Summary &amp;amp; What's Next: Fuel for the Engine
&lt;/h2&gt;

&lt;p&gt;We have engineered an airtight structural harness (&lt;a href="https://dev.to/gde/from-vibing-chaos-to-reliable-agents-the-what-why-and-how-of-harness-engineering-4ba0"&gt;Part 1&lt;/a&gt;) and fired up an autonomous, self-evaluating execution loop with binary rubrics, tool trajectories, and the Ratchet Principle.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Now, what fuels the loop?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If you feed an autonomous loop vague conversational vibes and hand-waving, you won't get software; you will get automated, looping chaos at 50 tokens a second.&lt;/p&gt;

&lt;p&gt;In &lt;strong&gt;Part 3&lt;/strong&gt;, we provide the ultimate fuel: &lt;strong&gt;Spec-Driven Development (SDD)&lt;/strong&gt;. We will explore:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Why code is disposable, but specifications are the permanent source of truth.&lt;/li&gt;
&lt;li&gt;Authentic production spec blueprints (&lt;code&gt;tasks/plan.md&lt;/code&gt;) with Three-Tier Operational Boundaries (&lt;em&gt;Always Do&lt;/em&gt;, &lt;em&gt;Ask First&lt;/em&gt;, &lt;em&gt;Never Do&lt;/em&gt;).&lt;/li&gt;
&lt;li&gt;Putting it all into practice with &lt;strong&gt;Google Antigravity&lt;/strong&gt;: the unified harness across IDE, Extension, CLI, and SDK.&lt;/li&gt;
&lt;li&gt;Native slash commands (&lt;code&gt;/grill-me&lt;/code&gt;, &lt;code&gt;/learn&lt;/code&gt;, &lt;code&gt;/goal&lt;/code&gt;, &lt;code&gt;/plan&lt;/code&gt;) vs formal SDD, and the &lt;strong&gt;4-Phase Hybrid Power Pattern&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;👉 &lt;strong&gt;Continue to Part 3: Spec-Driven Development For-the-Win: Disposable Code, Living Blueprints, and Building Like a Boss (Coming Soon)&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Before You Go
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Please share&lt;/strong&gt; 📢 this with anyone that you think will be interested. It might help them, and it really helps me!&lt;/li&gt;
&lt;li&gt;Please &lt;strong&gt;give me loads of claps&lt;/strong&gt;! 👏 (Just hold down the clap button.)&lt;/li&gt;
&lt;li&gt;Please &lt;strong&gt;leave a comment&lt;/strong&gt; 💬. Interaction is good!&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Add a star&lt;/strong&gt; ⭐ on my repos!&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Follow&lt;/strong&gt; 👉 and &lt;strong&gt;subscribe&lt;/strong&gt; 🔔, so you don’t miss my content.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  References and Useful Links
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Loop &amp;amp; Autonomous Systems
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://signals.forwardfuture.com/loop-library/" rel="noopener noreferrer"&gt;The Loop Library&lt;/a&gt; &amp;amp; &lt;a href="https://github.com/Forward-Future/loopy/tree/main/skills/loopy" rel="noopener noreferrer"&gt;Loopy Skill&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.rahuldhar.me/p/harness-engineering-vs-loop-engineering" rel="noopener noreferrer"&gt;&lt;em&gt;Harness Engineering vs. Loop Engineering&lt;/em&gt; by Rahul Dhar (The Pragmatic Tech Lead)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://datasciencedojo.com/blog/harness-engineering-vs-loop-engineering/" rel="noopener noreferrer"&gt;&lt;em&gt;Harness engineering vs loop engineering&lt;/em&gt; | Data Science Dojo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.mindstudio.ai/blog/loop-engineering-vs-harness-engineering" rel="noopener noreferrer"&gt;&lt;em&gt;Loop Engineering vs Harness Engineering: What's the Difference and Which Do You Need?&lt;/em&gt; | MindStudio&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://flowtivity.ai/blog/loop-engineering-the-feedback-cycle-that-makes-ai-agents-work/" rel="noopener noreferrer"&gt;&lt;em&gt;Loop Engineering: The Feedback Cycle That Turns AI Agents Into Reliable Workers&lt;/em&gt; | Flowtivity&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.codecentric.de/en/knowledge-hub/blog/loop-harness-context-engineering-explained" rel="noopener noreferrer"&gt;&lt;em&gt;Loop, Harness, Context Engineering: The Terms Explained&lt;/em&gt; | codecentric Knowledge Hub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=ew6gBJNzC5w" rel="noopener noreferrer"&gt;&lt;em&gt;I'm a Senior Google AI PM. Here's How I Build Loops (Finally, Loop Engineering Explained)&lt;/em&gt; (Shubham Saboo on Product Faculty)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Dazbo's Related Content
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/derailed-dash/harness-engineering-demo" rel="noopener noreferrer"&gt;&lt;em&gt;Harness Engineering Demo Repository&lt;/em&gt; on GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/gde/dialling-our-agents-to-11-agent-skills-you-need-to-be-using-2o2k"&gt;&lt;em&gt;Dialling Our Agents to 11: Agent Skills You Need to be Using!&lt;/em&gt; by Dazbo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/gde/dialling-our-agents-to-11-my-favourite-mcp-servers-3hbm"&gt;&lt;em&gt;Dialling Our Agents to 11: My Favourite MCP Servers&lt;/em&gt; by Dazbo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/gde/skills-sprawl-when-too-much-of-a-good-thing-confuses-your-ai-agent-4nij"&gt;&lt;em&gt;Skills Sprawl: When Too Much of a Good Thing Confuses Your AI Agent&lt;/em&gt; by Dazbo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/gde/meet-the-antigravity-extension-gemini-code-assist-on-steroids-in-whatever-ide-you-love-4p1n"&gt;&lt;em&gt;Meet the Antigravity Extension: Gemini Code Assist on Steroids, in Whatever IDE You Love&lt;/em&gt; by Dazbo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/gde/building-an-agentic-finops-platform-development-environment-setup-google-antigravity-mcps-and-4c43"&gt;&lt;em&gt;FinSavant Part 2: Building an Agentic FinOps Platform — Development Environment Setup, Google Antigravity, MCPs and Skills, and ADK Bootstrapping with Agents CLI&lt;/em&gt; by Dazbo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dazbo.co.uk" rel="noopener noreferrer"&gt;&lt;em&gt;Dazbo's Portfolio&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>harnessengineering</category>
      <category>loopengineering</category>
      <category>agenticai</category>
      <category>googleantigravity</category>
    </item>
    <item>
      <title>From Vibing Chaos to Reliable Agents: The What, Why, and How of Harness Engineering</title>
      <dc:creator>Darren "Dazbo" Lester</dc:creator>
      <pubDate>Mon, 28 Sep 2026 09:59:24 +0000</pubDate>
      <link>https://dev.to/gde/from-vibing-chaos-to-reliable-agents-the-what-why-and-how-of-harness-engineering-4ba0</link>
      <guid>https://dev.to/gde/from-vibing-chaos-to-reliable-agents-the-what-why-and-how-of-harness-engineering-4ba0</guid>
      <description>&lt;p&gt;You are in Part 1 of the series &lt;em&gt;"Beyond Vibe Coding: The Engineering Blueprint for Reliable AI Agents"&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  🗺️ The Series Roadmap: Beyond Vibe Coding
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;Agentic software development is drowning in fragmented buzzwords: Harness Engineering, Loop Engineering, Context Engineering, Spec-Driven Development… Are they competing frameworks? Redundant techniques? Or fundamentally different and essential?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This four-part series unifies these concepts into a single, cohesive architectural blueprint for building software with AI without writing code manually:&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Part 1: From Vibing Chaos to Reliable Agents: The What, Why, and How of Harness Engineering (This Article)&lt;/strong&gt;
We diagnose the issues of vibe coding, unpack the paradigm shift of &lt;em&gt;shifting developer interventions left&lt;/em&gt;, establish our bedrock formula (&lt;strong&gt;Agent = Model + Harness&lt;/strong&gt;), explore a motorsport analogy, and deconstruct deterministic foundations that make up a production developer environment.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Part 2:&lt;/strong&gt; &lt;a href="https://dev.to/gde/loop-engineering-in-the-harness-autonomous-self-correcting-systems-part-2-155e"&gt;&lt;strong&gt;Loop Engineering in the Harness: Autonomous, Self-Correcting Systems&lt;/strong&gt;&lt;/a&gt;
We fire up the dynamic runtime engine of the harness: deconstructing the loop components, establishing hybrid evaluation rubrics (deterministic tests + LLM goal fidelity + tool trajectory verification), and applying the Ratchet Principle.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Part 3: Spec-Driven Development For-the-Win: Disposable Code, Living Blueprints, and Building Like a Boss (Coming Soon)&lt;/strong&gt;
We explore Spec-Driven Development (where code is disposable and specifications are the real IP), master Google Antigravity’s unified developer harness and interactive slash commands (&lt;code&gt;/grill-me&lt;/code&gt;, &lt;code&gt;/plan&lt;/code&gt;, &lt;code&gt;/goal&lt;/code&gt;, &lt;code&gt;/boost&lt;/code&gt;, &lt;code&gt;/learn&lt;/code&gt;), and combine formal specs with tactical workflows via the 4-Phase Hybrid Power Pattern.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Part 4: Scaling the Harness: Practical Loop Patterns, ADK 2 Graphs, Recursive Harness², and Enterprise Production (Coming Soon)&lt;/strong&gt;
We unpack the anatomy of a loop iteration (&lt;code&gt;LIVING_MEMORY.md&lt;/code&gt;, ephemeral subagents, and beating attention dilution), demonstrate the four composable ways to wire loops into any repo (including Google ADK 2 graphs), explore Google Research’s recursive Harness² framework, and scale to enterprise production on Google Cloud.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Introduction: The Chaos of Vibe Coding
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmax46t070o2op5oqau1s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmax46t070o2op5oqau1s.png" alt="From Vibing Chaos to Harness Engineering" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Was your first vibe coding experience like mine? Type in a single prompt and then watch an entire application spring into existence. It felt like wizardry.&lt;/p&gt;

&lt;p&gt;It was clear that software development had fundamentally changed. We had entered the era of “vibe coding” — that intoxicating workflow where you lean back in your chair, sip your brew, prompt an LLM with a breezy idea, and casually mash the approval button while the model writes hundreds of lines of code across half a dozen files.&lt;/p&gt;

&lt;p&gt;For quick hobby prototypes, weekend experiments, or throwing together an interactive mock-up to impress a client on a Friday afternoon, vibe coding is both effective and &lt;em&gt;brilliant fun&lt;/em&gt;. You watch a terminal stream lines of code at lightspeed, and for a fleeting moment you feel like an omnipotent 100x developer. You can now build things in hours that would have once taken a competent coder months.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Then Monday morning arrives.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;When you attempt to take your vibe-coded solution anywhere near a real production environment, reality hits you like a cold, wet Monday in London. What felt like intoxicating velocity on Friday turns into an architectural crime scene by Monday. The code might run, but beneath the surface lies a tangled web of subtle bugs, orphaned functions, unverifiable assumptions, and &lt;em&gt;utter nonsense&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;You quickly uncover the dirty secret behind unconstrained vibing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Hallucination City:&lt;/strong&gt; The model confidently invents deprecated API methods and fictitious URLs, synthesises nonexistent package dependencies, and hallucinates framework features that simply don’t exist. Once an agent hallucinates a dependency, every subsequent turn doubles-down on the fiction, inventing bizarre workarounds for libraries that were never real in the first place.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Alert &amp;amp; “LGTM” Fatigue:&lt;/strong&gt; After reading your forty-seventh sprawling diff in two hours, your eyes glaze over. You find yourself mindlessly clicking “Approve” or typing “LGTM” without actually understanding or checking the changes, silently hoping the AI knows what it’s doing. (Spoiler: &lt;em&gt;it doesn’t.&lt;/em&gt; You haven’t eliminated manual labour; you have merely swapped creative software engineering for bleary-eyed cursory proofreading.)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Solutions That Don’t Do What You Wanted:&lt;/strong&gt; The code runs without syntax errors, but the actual business logic subtly diverges from what you originally intended. Maybe because you didn’t really know what you wanted in the first place, and you just hope that the model has magically filled in all the blanks in your fluffy request.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unmaintainable, Inscrutable Code:&lt;/strong&gt; The agent generates dense blocks of code without architectural coherence. It stitches together three different design patterns across four files. You don’t understand how it works and you haven’t really checked it. And you’d probably never reveal the code to your competent peers. &lt;em&gt;“What if they actually look at this?”&lt;/em&gt; Your code was tech-debt on day one.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No Documentation:&lt;/strong&gt; Zero README updates, no Architecture Decision Records (ADRs), no API contracts, and no inline explanations of why specific trade-offs were made. The key knowledge that maybe lives in your head is completely absent from the documentation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Insecure &amp;amp; Risky:&lt;/strong&gt; Hardcoded secrets, wide-open IAM permissions, complete absence of rate limits, and unescaped SQL queries slipped into the codebase because the agent prioritised making the code run over making it safe. Maybe you didn’t like a warning in a log and you told the agent &lt;em&gt;“Make this warning disappear.”&lt;/em&gt; The agent said: &lt;em&gt;“Hold my beer.”&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Inefficient Token Use &amp;amp; The Manual Loop Furnace:&lt;/strong&gt; You find yourself trapped in a soul-crushing manual loop: copy terminal error → paste into chat → get half-baked fix → copy next error → watch the context window bloat → watch your token bill skyrocket. You aren’t architecting software; you are acting as an organic clipboard between a compiler and an LLM. Inevitably, unless you happen to be paying for a premium model subscription, you’re going to hit your model quota.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lack of Scalability &amp;amp; Portability:&lt;/strong&gt; The code works on your machine, under your specific node or python version, with zero containerisation or repeatable environment configuration. Hand it to a colleague or push it to CI, and it instantly shatters. &lt;em&gt;Onboarding friction&lt;/em&gt;, anyone?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Purpose Drift:&lt;/strong&gt; By turn eight of a messy conversation, the model has completely forgotten the initial rules and constraints you laid out in turn one. (Assuming you specified any constraints at all.) It begins re-inventing components it already built or quietly undoing your earlier bug fixes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The conclusion is inescapable: &lt;strong&gt;you cannot ship vibes to production.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Yet, none of us wants to retreat to typing out thousands of lines of boilerplate by hand. The goal remains what it has always been: &lt;strong&gt;to create robust, scalable software solutions without writing code manually&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In an insightful &lt;a href="https://www.youtube.com/watch?v=F8EZJAm9iO8" rel="noopener noreferrer"&gt;Google Cloud Tech interview&lt;/a&gt; with Tilde Thurium, &lt;strong&gt;Ryan Lopopolo&lt;/strong&gt; (Principal Engineer, Agentic Cloud Platform @ Google, who first coined the term &lt;em&gt;“agent harness”&lt;/em&gt;) laid out his own radical ambition: to never write code by hand again. As Ryan wryly admitted: &lt;em&gt;“I aspire to be a lazy programmer.”&lt;/em&gt; Don’t we all?&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/F8EZJAm9iO8" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Having demonstrated that teams can build and ship massive production systems with zero manual typing by establishing that &lt;em&gt;“humans steer, agents execute”&lt;/em&gt;, Lopopolo proved that hands-off development is genuinely achievable.&lt;/p&gt;

&lt;p&gt;The answer isn’t to abandon AI agents or wait for newer models; it is to fundamentally change how we construct, control, and constrain them.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Paradigm Shift: Shifting Developer Interventions Left
&lt;/h3&gt;

&lt;p&gt;To understand why unconstrained vibe coding collapses, we should look at &lt;em&gt;where&lt;/em&gt; developers are forced to spend their energy.&lt;/p&gt;

&lt;p&gt;In naive AI interactions, developer intervention happens almost entirely &lt;strong&gt;on the right&lt;/strong&gt;. That is: downstream, after the code has already been generated. You spend your afternoon scrolling through hundreds of lines of inscrutable diffs, tweaking chat prompts to fix syntax quirks, or rewriting hallucinations. You are perpetually reacting to failure after the fact, acting as an exhausted organic filter for broken output.&lt;/p&gt;

&lt;p&gt;Harness engineering &lt;strong&gt;shifts developer intervention to the left&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Instead of manually reviewing broken outputs or wrestling with repetitive errors downstream, you invest your engineering effort upstream &lt;em&gt;before&lt;/em&gt; the agent ever runs. You engineer the environment: defining rules, embedding automated linters and type-checkers, configuring deterministic sandboxes, and establishing clear evaluation rubrics. When the agent operates within an engineered environment, failures are caught and corrected autonomously inside the execution loop, long before a human ever inspects the resulting pull request.&lt;/p&gt;

&lt;p&gt;Enter &lt;strong&gt;Harness Engineering&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8tfrykrvuyq15f5ojs4f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8tfrykrvuyq15f5ojs4f.png" alt="The Paradigm Shift" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Bedrock: If It's Not the Model, It's the Harness
&lt;/h2&gt;

&lt;p&gt;To understand what &lt;em&gt;harness engineering&lt;/em&gt; is, you must start with this fundamental equation:&lt;/p&gt;

&lt;p&gt;

&lt;/p&gt;
&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord text"&gt;&lt;span class="mord"&gt;Agent&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord text"&gt;&lt;span class="mord"&gt;Model&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;+&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord text"&gt;&lt;span class="mord"&gt;Harness&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;And with this comes the ultimate maxim of modern AI development:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;“If it’s not the model, it’s the harness.”&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fixy5peueohcsbu5w6v1p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fixy5peueohcsbu5w6v1p.png" alt="The Agent: Model + Harness" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We have been conditioned by tech headlines to obsess over frontier models. Every week brings another benchmark, another parameter increase, and another claim of AGI just around the corner. But here is the hard reality: &lt;strong&gt;the harness is arguably more important than the model.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;An okay, cost-effective model housed within a robust harness will consistently outperform a bleeding-edge frontier model with a poor harness. Why? Because the model is inherently probabilistic, whereas serious software engineering demands determinism. The harness is what bridges that chasm. It supplies the missing structure: living memory, automated validation, static analysis, type checking, sandboxing, and execution guardrails.&lt;/p&gt;

&lt;p&gt;Think of it like high-performance motorsport:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fh45h2rpydt5uit1tx31b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fh45h2rpydt5uit1tx31b.png" alt="The Motorsport Analogy for Agents and the Harness" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The Model is the Driver:&lt;/strong&gt; Incredibly talented, capable of split-second reasoning and creative problem-solving, but prone to fatigue, distraction, and occasional moments of reckless overconfidence. Left entirely to their own devices on an open airfield, they might pull off some breathtaking doughnuts, but they can’t win a grand prix.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Entire Race Car IS the Harness:&lt;/strong&gt; The complete, precision-engineered machine built to translate the driver’s intent into track-winning performance:&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Engine &amp;amp; Transmission (Loop Engineering):&lt;/strong&gt; The internal dynamic execution engine of the harness. It delivers torque to the wheels through a disciplined cycle of intake, combustion, and telemetry. Iterative execution, continuous evaluation, and immediate feedback cycles.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Chassis (Structural Harness):&lt;/strong&gt; The living rules (&lt;code&gt;AGENTS.md&lt;/code&gt; / &lt;code&gt;GEMINI.md&lt;/code&gt;), directory layouts, and sandboxed runtimes that keep the car glued to the tarmac, dictating the exact physical limits of where the vehicle can steer.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Brakes &amp;amp; Pit Telemetry (Safety &amp;amp; Evaluation Gates):&lt;/strong&gt; The deterministic test suites and escalation protocols that prevent the driver from wrapping the machine around a barrier at 180 mph.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You wouldn’t put Lewis Hamilton behind the wheel of a V12 engine block with no chassis or brakes and expect him to finish a single lap at Silverstone, let alone win the race. So why do the same with agentic software development and expect robust results?&lt;/p&gt;

&lt;h3&gt;
  
  
  ⚠️ Dazbo's Battle Scar: The Model Upgrade Fallacy
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Whenever an agentic workflow breaks down in development — falling into repetitive loops, introducing subtle runtime bugs, or failing to follow architectural patterns — the instinctive developer reaction is:&lt;/em&gt; “We need a smarter model. Let’s switch to the latest 2-trillion parameter frontier model.”&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Almost every time, this is a fallacy. Upgrading the model without improving your harness simply means your agent will generate more articulate, harder-to-spot hallucinations at four times the token cost. If your agent is failing, don’t reach for a bigger model first. Ask yourself:&lt;/em&gt; Did the harness enforce a test? Did the harness provide the exact schema? Did the harness restate the goal? &lt;em&gt;If it’s not the model, it’s the harness!&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Crucially, &lt;strong&gt;the harness is model-agnostic&lt;/strong&gt;. Whether you are routing requests through a cost-effective, high-velocity workhorse like &lt;code&gt;gemini-3.8-flash&lt;/code&gt;, or a deep-reasoning powerhouse, a well-engineered harness remains stable, repeatable, and robust. You can hot-swap the model under the hood without having to redesign your entire engineering lifecycle.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Model is a Commodity; The Harness is the IP
&lt;/h3&gt;

&lt;p&gt;This reveals a fundamental commercial reality of AI software engineering. As my friend and fellow Google Developer Expert &lt;strong&gt;Jaroslav Pantsjoha (JP)&lt;/strong&gt; highlighted in &lt;a href="https://medium.com/google-cloud/the-ai-native-developer-experience-part-2-harness-engineering-with-google-antigravity-7fb72dab243f" rel="noopener noreferrer"&gt;his analysis of the AI-native developer experience&lt;/a&gt;: &lt;strong&gt;the model is a commodity; the harness is where your true competitive advantage and intellectual property reside.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Every organisation has access to the exact same frontier foundational models via public APIs. Simply renting access to raw model intelligence provides zero lasting competitive advantage. &lt;strong&gt;Your true intellectual property and your team’s operational velocity live entirely inside your harness&lt;/strong&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Your living rules and architectural guardrails&lt;/strong&gt; that encode decades of hard-won domain knowledge.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Your curated suite of tool integrations and MCP servers&lt;/strong&gt; that securely bridge AI agents into your private internal databases and microservices.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Your deterministic evaluation rubrics and automated test harnesses&lt;/strong&gt; that guarantee safety and compliance before any code reaches production.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Your version-controlled living specifications&lt;/strong&gt; that turn disposable AI code into maintained, documented, and resilient software assets.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Foundational models will continue to be commoditised, upgraded, and replaced. But a well-architected enterprise harness compounds in value with every single engineering iteration.&lt;/p&gt;

&lt;h2&gt;
  
  
  Untangling the Triad: Context, Harness, and Loop Engineering
&lt;/h2&gt;

&lt;p&gt;Before we deconstruct the components, it is worth clarifying how three terms frequently heard across the industry map directly back to our bedrock formula (&lt;strong&gt;Agent = Model + Harness&lt;/strong&gt;):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Context Engineering:&lt;/strong&gt; Determines what the agent &lt;strong&gt;knows&lt;/strong&gt;. It is the cognitive payload the harness feeds to the model, including hierarchical rules (&lt;code&gt;AGENTS.md&lt;/code&gt; or &lt;code&gt;GEMINI.md&lt;/code&gt; that can be global, team, domain, or project-specific), active retrieval (RAG), agent skills, and other sources of knowledge.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Structural Harness Engineering:&lt;/strong&gt; Determines what the agent &lt;strong&gt;can touch and where it runs&lt;/strong&gt;. It provides the deterministic environment: tools, APIs, MCP servers, sandboxed execution runtimes, security guardrails, living file state, and blast-radius (damage control).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Loop Engineering:&lt;/strong&gt; Determines how the agent &lt;strong&gt;iterates and converges&lt;/strong&gt; over time. It is &lt;strong&gt;the dynamic runtime engine of the harness&lt;/strong&gt; ; the autonomous process of observing, acting, judging against rubrics, recording memory, and knowing when to stop.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Crucially, &lt;strong&gt;they are not three competing systems; loop and context are the internal functional dimensions of the harness itself.&lt;/strong&gt; If context is the agent’s briefing pack and the loop is its working cadence, the harness is the complete laboratory workbench in which all of it takes place.&lt;/p&gt;

&lt;p&gt;And we can see that state (such as markdown files) plays a significant role in all three.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkg63sa3z2iitut81jzgd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkg63sa3z2iitut81jzgd.png" alt="Context, Harness and Loop Engineering" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Deconstructing the Harness: The Deterministic Foundations
&lt;/h2&gt;

&lt;p&gt;If the model represents the non-deterministic, probabilistic core of our system, the harness represents everything else: the &lt;strong&gt;deterministic components&lt;/strong&gt; that guide, restrain, and validate every single action the model takes.&lt;/p&gt;

&lt;p&gt;So, what actually lives inside a robust developer harness?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F47kuc403syu1a1gkzqz0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F47kuc403syu1a1gkzqz0.png" alt="The Foundations of the Developer Harness" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let’s break down the essential layers:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Hierarchical Context &amp;amp; Living Rules: "De-Slopping" by Design
&lt;/h3&gt;

&lt;p&gt;Your agent should never have to guess your engineering standards, architectural decisions, or toolchain preferences. In an ad-hoc vibe coding setup, you might type: &lt;em&gt;“Please write clean Python and test it.”&lt;/em&gt; The model nods, writes an unformatted script, tests it with a couple of inline assert statements, and calls it a day.&lt;/p&gt;

&lt;p&gt;In her analysis &lt;a href="https://www.builder.io/blog/de-slop-ai-generated-codebase" rel="noopener noreferrer"&gt;&lt;em&gt;How to De-Slop an AI-Generated Codebase&lt;/em&gt;&lt;/a&gt;, Alice Moore highlights why telling an AI to &lt;em&gt;“clean this up”&lt;/em&gt; or &lt;em&gt;“write clean code”&lt;/em&gt; inevitably fails: the instruction is too vague. AI “slop” can only be prevented by translating human taste into &lt;strong&gt;concrete, non-negotiable rules&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In an engineered harness, we establish our context in files like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Global Configuration (&lt;code&gt;GEMINI.md&lt;/code&gt; or &lt;code&gt;AGENTS.md&lt;/code&gt;):&lt;/strong&gt; Cross-project standards including language preferences, mandatory package managers (e.g. using &lt;code&gt;uv&lt;/code&gt; for Python), security baseline rules, and zero-tolerance policies for inline execution hacks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Workspace-Specific Context (&lt;code&gt;my-project/GEMINI.md&lt;/code&gt;):&lt;/strong&gt; Architecture blueprints, directory layouts, data sources, and project goals.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automated Guardrails:&lt;/strong&gt; Explicit rules that we must always adhere to. For example, performing static analysis after each change. Or, for example, requiring the agent to practice strict Test-Driven Development (TDD). I.e. writing the failing test before implementing code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Documentation Rules:&lt;/strong&gt; Mandatory upkeep of core documentation (READMEs, Architecture Decision Records, product specs, task lists) using standardised workflows so the codebase never drifts into an undocumented quagmire.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To see what this looks like in practice, here is an authentic snippet from my own global &lt;code&gt;GEMINI.md&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gh"&gt;# Agent Execution Guardrails &amp;amp; Standards&lt;/span&gt;

&lt;span class="gu"&gt;## Python Guidance &amp;amp; Tooling&lt;/span&gt;
&lt;span class="p"&gt;
-&lt;/span&gt; &lt;span class="gs"&gt;**Environment Source of Truth**&lt;/span&gt;: Respect the Python version defined in
  &lt;span class="sb"&gt;`pyproject.toml`&lt;/span&gt;. For new greenfield projects, default to &lt;span class="sb"&gt;`python 3.13`&lt;/span&gt;.
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="sb"&gt;`uv`&lt;/span&gt; is the preferred tool for Python package and environment management.
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**Avoid Inline `python -c` Commands**&lt;/span&gt;: Do NOT execute inline Python snippets
  using &lt;span class="sb"&gt;`python -c "..."`&lt;/span&gt; or &lt;span class="sb"&gt;`python3 -c "..."`&lt;/span&gt;. Because Antigravity cannot 
  safely prefix-match arbitrary inline code payloads, this triggers a manual 
  approval prompt every time. Instead, write one-off helper logic to a 
  scratch script in your scratch directory and execute it cleanly via 
  &lt;span class="sb"&gt;`uv run python scratch/helper.py`&lt;/span&gt;.
&lt;span class="p"&gt;-&lt;/span&gt; Always include top-of-module docstrings that explain what a given .py 
  file does, why it exists (i.e. the value it provides) and an outline of 
  how it works.
&lt;span class="p"&gt;-&lt;/span&gt; Use rich (&lt;span class="sb"&gt;`pip install rich`&lt;/span&gt;) when building console / CLI applications.
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**Zero-Tolerance for Suppression Hacks**&lt;/span&gt;: Never bypass linter or 
  type-checker errors using &lt;span class="sb"&gt;`# noqa`&lt;/span&gt;, &lt;span class="sb"&gt;`# type: ignore`&lt;/span&gt;, or &lt;span class="sb"&gt;`@ts-ignore`&lt;/span&gt; 
  comments. Resolve the underlying type contract or architectural root cause.
&lt;span class="p"&gt;-&lt;/span&gt; When adding features or making changes that are anything beyond trivial, 
  &lt;span class="gs"&gt;**use TDD**&lt;/span&gt;. Create the test, verify it fails, make the change, and then verify 
  the test passes.
&lt;span class="p"&gt;-&lt;/span&gt; To ensure Python code adheres to required standards, the following 
  commands &lt;span class="gs"&gt;**must**&lt;/span&gt; be run after creating or modifying any &lt;span class="sb"&gt;`.py`&lt;/span&gt; files:
  &lt;span class="p"&gt;```&lt;/span&gt;&lt;span class="nl"&gt;bash
&lt;/span&gt;  uvx codespell@latest &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="c"&gt;# check spelling and show summary&lt;/span&gt;
  uvx ruff@latest check &lt;span class="nt"&gt;--fix&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="c"&gt;# perform static checks and auto-fix&lt;/span&gt;
  &lt;span class="p"&gt;```&lt;/span&gt;

&lt;span class="gu"&gt;## Agent and AI Development&lt;/span&gt;
&lt;span class="p"&gt;
-&lt;/span&gt; NEVER try to downgrade a Gemini model in code or variables. E.g. NEVER 
  try to change &lt;span class="sb"&gt;`gemini-3.8-flash`&lt;/span&gt; to &lt;span class="sb"&gt;`gemini-3-flash`&lt;/span&gt;.
&lt;span class="p"&gt;-&lt;/span&gt; Unless otherwise instructed, use the latest generally available Gemini 
  models available; always check what the latest is. This also goes for 
  image generation.
&lt;span class="p"&gt;-&lt;/span&gt; Unless I say otherwise, agents should be built using the Google ADK 
  (&lt;span class="sb"&gt;`google-adk`&lt;/span&gt;) and the Google Gen AI (&lt;span class="sb"&gt;`google-genai`&lt;/span&gt;) packages. 
&lt;span class="p"&gt;-&lt;/span&gt; AVOID using the &lt;span class="sb"&gt;`google-generativeai`&lt;/span&gt; package. This is deprecated in 
  favour of the newer GenAI &lt;span class="sb"&gt;`google-genai`&lt;/span&gt; SDK.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We’re not politely pleading with the model. We are creating rigid rails.&lt;/p&gt;

&lt;p&gt;The rule banning inline &lt;code&gt;python -c&lt;/code&gt; snippets is a classic harness engineering battle scar. In a sandboxed developer environment, the execution engine auto-approves safe binary prefixes (such as &lt;code&gt;uv run python ...&lt;/code&gt;). When an unconstrained model starts generating dynamic inline code strings, the runtime cannot prefix-match the payload and is forced to interrupt the developer with a manual approval prompt every time it makes a minor tweak to the Python it wants to execute… Every ten seconds!&lt;/p&gt;

&lt;p&gt;Similarly, the rule forbidding &lt;code&gt;# type: ignore&lt;/code&gt; and &lt;code&gt;# noqa&lt;/code&gt; suppressions closes a notorious AI loophole. When confronted with strict linting or typing rules, an unsupervised LLM will frequently take the path of least resistance by slapping suppression comments across the file to silence the compiler. By outlawing suppressions in the harness rules, the model is compelled to fix the actual defect.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Living State &amp;amp; Version-Controlled Memory
&lt;/h3&gt;

&lt;p&gt;Human software engineers don’t attempt to hold an entire multi-week project in their brains; we maintain backlog boards, write technical specifications, document decisions, and keep scratchpads.&lt;/p&gt;

&lt;p&gt;Yet developers routinely expect an AI model to hold twenty architectural considerations across a forty-turn chat window. The moment the conversation grows long, the context window compacts, and the agent quietly forgets earlier decisions. And let’s not forget the &lt;em&gt;“lost-in-the-middle”&lt;/em&gt; problem that we frequently observe in models.&lt;/p&gt;

&lt;p&gt;The harness solves this by providing agents with structured, file-backed &lt;strong&gt;living state&lt;/strong&gt;. Although there are no rigid rules for &lt;em&gt;HOW&lt;/em&gt; you structure this, here are some suggestions from me:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Strategic &amp;amp; Architectural Truth (The Blueprints):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;PRODUCT.md&lt;/code&gt;&lt;/strong&gt;: Defines the business “why”, user personas and user stories, core problem statement, and explicit non-goals (what the system is deliberately &lt;em&gt;not&lt;/em&gt; building, preventing the agent from over-engineering features you never asked for).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;SPEC.md&lt;/code&gt;&lt;/strong&gt;: Machine-readable functional requirements, API contracts, and behavioural scenarios (Given / When / Then).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;ARCHITECTURE.md&lt;/code&gt;&lt;/strong&gt;: System topology, component boundaries, database schemas, data flow and design decisions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;DESIGN.md&lt;/code&gt;&lt;/strong&gt;: UI design, styling rules, token definitions (colours, typography, spacing), and accessibility constraints; we can even export or synchronise this file with tools like Google Stitch via MCP.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Operational &amp;amp; Execution State (The Working Memory):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;TODO.md&lt;/code&gt;&lt;/strong&gt; (or active backlog): Real-time checklists where tasks are marked off as completed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;plan.md&lt;/code&gt;&lt;/strong&gt;: Phased vertical slices and dependencies mapped out for the immediate objective.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Transient Execution State (The Scratchpad):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;scratch/&lt;/code&gt;&lt;/strong&gt;: Ephemeral execution notes, raw compiler traces, and intermediate data files that persist across model turns without polluting Git history. You would exclude this folder in your &lt;code&gt;.gitignore&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;(We will explore how to author, stress-test, and execute these living blueprints in depth in Part 3: Spec-Driven Development For-the-Win. Coming soon!)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Because these files are stored in standard Markdown directly in the workspace, &lt;strong&gt;they can be version-controlled with Git and shared seamlessly across developer sessions and different machines&lt;/strong&gt;. If an agent session crashes, if your laptop runs out of battery, or if you hand the task over to a colleague across the globe, the harness preserves the living state. The agent simply reads the task list on turn one and resumes exactly where it left off.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Agent Tools: Grounding Models in the Real World
&lt;/h3&gt;

&lt;p&gt;Language models in a vacuum are just predictive text generators; they interact with the outside world through tools. A robust harness equips the agent with a multi-layered execution surface:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Native Functions:&lt;/strong&gt; Strongly typed functions in the code, for fast deterministic operations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sandboxed Shell and CLIs:&lt;/strong&gt; Compilers, linters (&lt;code&gt;ruff&lt;/code&gt;, &lt;code&gt;eslint&lt;/code&gt;), test runners (&lt;code&gt;pytest&lt;/code&gt;), package managers (&lt;code&gt;uv&lt;/code&gt;, &lt;code&gt;npm&lt;/code&gt;), and cloud CLIs (e.g. &lt;code&gt;gcloud&lt;/code&gt;) executed inside isolated shell environments.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Model Context Protocol (MCP):&lt;/strong&gt; A standard that lets agents discover and execute tools without writing bespoke glue code for every service.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  ⚠️ Dazbo's Battle Scar: Tool Sprawl &amp;amp; Choice Paralysis
&lt;/h4&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;When developers first discover MCP, the temptation is to connect twenty different servers simultaneously: GitHub, Slack, Postgres, BigQuery, GKE, Firestore, Stitch, Confluence, Jira, Cloud Logging…&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Don’t do it. Connecting 20 MCP servers could easily dump 150+ tool schemas into your model’s context. That’s a lot of wasted tokens before you’ve even typed an instruction. Worse, models experience&lt;/em&gt; tool choice paralysis &lt;em&gt;and routing collisions. As I detailed in&lt;/em&gt; &lt;a href="https://dev.to/gde/dialling-our-agents-to-11-my-favourite-mcp-servers-3hbm"&gt;Dialling Our Agents to 11: My Favourite MCP Servers&lt;/a&gt;&lt;em&gt;, keep your active MCP server suite lean, curated, and strictly relevant to the task at hand.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  4. On-Demand Context: Progressive Disclosure via Agent Skills
&lt;/h3&gt;

&lt;p&gt;Flooding an LLM’s context window with thousands of lines of reference manuals on every turn is a great way to confuse your model and increase your token costs.&lt;/p&gt;

&lt;p&gt;Instead, the harness can use &lt;em&gt;agent skills&lt;/em&gt;, which use a mechanism called &lt;strong&gt;progressive disclosure&lt;/strong&gt;  &lt;strong&gt;to load on-demand&lt;/strong&gt;. Progressive disclosure operates in three levels:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Level 1 (Metadata):&lt;/strong&gt; At startup, the agent only reads tiny YAML frontmatter headers (e.g. name and trigger description, typically consuming under 100 tokens).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Level 2 (Instructions):&lt;/strong&gt; Only when a relevant task is initiated does the agent dynamically load the full &lt;code&gt;SKILL.md&lt;/code&gt; instruction set.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Level 3 (Resources):&lt;/strong&gt; Deep reference scripts, schemas, and templates are only pulled into context when needed.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Your agent stays lightning-fast, burns minimal tokens, and possesses instant access to all the knowledge and operational expertise it needs.&lt;/p&gt;

&lt;p&gt;Feels a bit like cheating, doesn’t it?&lt;/p&gt;

&lt;h4&gt;
  
  
  ⚠️ Dazbo's Battle Scar: Skills Sprawl &amp;amp; Context Pollution
&lt;/h4&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;If skills are so effective, why not install hundreds of them?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;As I explored in&lt;/em&gt; &lt;a href="https://dev.to/gde/skills-sprawl-when-too-much-of-a-good-thing-confuses-your-ai-agent-4nij"&gt;Skills Sprawl: When Too Much of a Good Thing Confuses Your AI Agent&lt;/a&gt;&lt;em&gt;, skills hoarding is a trap.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fuf3sykrvfnyc8zqjh4ap.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fuf3sykrvfnyc8zqjh4ap.png" alt="Too many skills — It’s a trap!" width="661" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Even though Level 1 progressive disclosure reads only the YAML frontmatter, loading 150+ skills can easily inject over 15,000 tokens and routing overhead into every single model turn.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The result? Severe LLM decision fatigue, tool selection degradation, and skill routing collisions. If your agent is building a Python cloud backend, it shouldn’t be wading through metadata for React video rendering or mobile UI frameworks. Curate your active skills, prune what you don’t use, and disable non-essential sub-skills in your configuration. A disciplined harness is a clean harness. (For a deep dive into the top skills I rely on daily, check out&lt;/em&gt; &lt;a href="https://dev.to/gde/dialling-our-agents-to-11-agent-skills-you-need-to-be-using-2o2k"&gt;Dialling Our Agents to 11: Agent Skills You Need to be Using!&lt;/a&gt;&lt;em&gt;.)&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  5. Packaging Knowledge &amp;amp; Capability: The Rules, Skills, and MCP Triad
&lt;/h3&gt;

&lt;p&gt;Once you begin equipping your harness with these deterministic components, an obvious engineering question arises: &lt;em&gt;How do you manage all this?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In practice, we organise with three complementary layers:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Rules (The Guardrails &amp;amp; Standards):&lt;/strong&gt; Standing instructions that ensure compliance (e.g. safe command syntax, directory layouts, and security policies).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MCP Servers (The Tools &amp;amp; Senses):&lt;/strong&gt; Execution interfaces that connect the agent to external infrastructure, databases, and APIs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Agent Skills (The Procedural Playbooks):&lt;/strong&gt; On-demand workflows and recipes that teach the agent &lt;em&gt;how&lt;/em&gt; and &lt;em&gt;when&lt;/em&gt; to use those tools effectively.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;While open protocols like MCP have standardised the tool layer, there is not yet a single universal industry standard for how the entire capability stack should be packaged.&lt;/p&gt;

&lt;p&gt;However, an increasingly popular architectural pattern — supported natively by developer harnesses like &lt;strong&gt;Google Antigravity&lt;/strong&gt; — is the &lt;strong&gt;Plugin&lt;/strong&gt;. Rather than forcing developers to manually wire up an MCP server, write separate prompt rules, and install five standalone skills, a plugin acts as an aggregated delivery vehicle:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjcs5q75h6loay2bu1azz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjcs5q75h6loay2bu1azz.png" alt="The Plugin" width="800" height="358"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A prime example of this pattern in the Google ecosystem is the &lt;strong&gt;google-cloud-developer plugin&lt;/strong&gt;, which looks like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Packaging Manifest (&lt;code&gt;plugin.json&lt;/code&gt;):&lt;/strong&gt; The schema descriptor defining metadata, versioning, and dependencies.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Standing Safety Rules (&lt;code&gt;rules/*.md&lt;/code&gt;):&lt;/strong&gt; Markdown rules (like google-cloud-discovery.md) that establish pre-flight command validation and guardrails.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Modular Agent Skills (&lt;code&gt;skills/*/SKILL.md&lt;/code&gt;):&lt;/strong&gt; Individual skill directories with YAML frontmatter headers and procedural Markdown instructions — such as google-cloud-recipe-auth, gcloud, and dynamic discovery (finding-google-skills).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tool Connectivity (&lt;code&gt;mcp.json&lt;/code&gt;):&lt;/strong&gt; A JSON configuration declaring active MCP endpoints — such as the streamable-HTTP connection to Google's official developer-knowledge server.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;google-cloud-developer/
├── plugin.json                    # Plugin metadata &amp;amp; agent-plugins.org schema
├── mcp.json                       # MCP server connection endpoints
├── rules/
│   └── google-cloud-discovery.md  # Standing guardrails &amp;amp; catalog rules
└── skills/
    ├── finding-google-skills/
    │   └── SKILL.md               # Dynamic on-demand catalog discovery
    ├── gcloud/
    │   └── SKILL.md               # Gcloud CLI validation &amp;amp; execution
    └── google-cloud-recipe-auth/
        └── SKILL.md               # Authentication recipes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Whether packaged as composite plugins or managed as standalone assets, the goal is identical: &lt;strong&gt;providing agents with both the architectural rules and the deep domain knowledge required to execute safely.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  My Curated Production Toolkit
&lt;/h3&gt;

&lt;p&gt;In my own daily engineering workflow, I rely on a focused blend of plugins and standalone skills, which include (but are not limited to):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/google/skills/tree/main/plugins/cloud/google-cloud-developer" rel="noopener noreferrer"&gt;&lt;code&gt;google-cloud-developer&lt;/code&gt; plugin&lt;/a&gt;:&lt;/strong&gt; Deep GCP architectural rules, safe execution guardrails, and native developer knowledge retrieval.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/google/agents-cli/tree/main/skills" rel="noopener noreferrer"&gt;&lt;code&gt;Google Agents CLI&lt;/code&gt; (ADK)&lt;/a&gt;:&lt;/strong&gt; Coding best practices, scaffolding, and deployment blueprints for building AI agents with the Google Agent Development Kit.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/google/skills/tree/main/skills/cloud/agent-platform-eval-flywheel" rel="noopener noreferrer"&gt;&lt;code&gt;agent-platform-eval-flywheel&lt;/code&gt;&lt;/a&gt;:&lt;/strong&gt; Google Cloud's evaluation flywheel methodology for measuring agent quality, LLM-as-judge scoring, and regression datasets.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/addyosmani/agent-skills/tree/main/skills/spec-driven-development" rel="noopener noreferrer"&gt;&lt;code&gt;spec-driven-development&lt;/code&gt;&lt;/a&gt;:&lt;/strong&gt; Bridges intent to code by generating machine-executable specifications and behavioural contracts before coding begins (the focus of Part 3).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/addyosmani/agent-skills/tree/main/skills/test-driven-development" rel="noopener noreferrer"&gt;&lt;code&gt;test-driven-development&lt;/code&gt;&lt;/a&gt;:&lt;/strong&gt; Enforces strict red-green-refactor loops, guaranteeing code isn't accepted until automated test suites pass.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/addyosmani/agent-skills/tree/main/skills/code-review-and-quality" rel="noopener noreferrer"&gt;&lt;code&gt;code-review-and-quality&lt;/code&gt;&lt;/a&gt;:&lt;/strong&gt; Automated multi-axis code reviews evaluating maintainability, security, and simplicity before changes enter the main branch.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/vercel-labs/skills" rel="noopener noreferrer"&gt;&lt;strong&gt;Vercel's &lt;code&gt;find-skills&lt;/code&gt;&lt;/strong&gt;&lt;/a&gt;: Dynamic skill discovery, allowing the agent to find and fetch installable skills from public registries on-demand without manual preloading.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/derailed-dash/dazbo-agent-skills/tree/main/skills/organise-agent-skills" rel="noopener noreferrer"&gt;&lt;code&gt;organise-agent-skills&lt;/code&gt;&lt;/a&gt;:&lt;/strong&gt; My own skill for auditing installed skills, pruning token overhead, and managing on-demand progressive disclosure to prevent skills sprawl.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/derailed-dash/dazbo-agent-skills/tree/main/skills/maintaining-core-documentation" rel="noopener noreferrer"&gt;&lt;code&gt;maintaining-core-documentation&lt;/code&gt;&lt;/a&gt;:&lt;/strong&gt; My own agent skill for synchronising READMEs, architectural docs, and task lists whenever code changes.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  6. Sandboxing &amp;amp; Blast-Radius Containment
&lt;/h3&gt;

&lt;p&gt;A robust harness never allows an agent unfettered access to host operating systems or production networks. Through containerised agent sandboxes, filesystem isolation, and execution policies, the harness establishes hard boundaries.&lt;/p&gt;

&lt;p&gt;If an agent attempts an unreviewed destructive action — such as dropping a database table, executing an unsandboxed shell command that alters host configuration, or modifying &lt;code&gt;.git/&lt;/code&gt; internal objects — the harness halts execution and demands explicit human verification. Sandboxing transforms autonomous agents from dangerous mavericks into safe, bounded wingmen. (See what I did there?)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjmwnkyg2c30r4m88qdpn.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjmwnkyg2c30r4m88qdpn.jpg" alt="Maverick — can be your wingman" width="737" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  7. Observability &amp;amp; Trajectory Monitoring: Beyond Traditional Logging
&lt;/h3&gt;

&lt;p&gt;In traditional software engineering, when a service fails, we inspect a deterministic stack trace and a linear log file: line 42 threw a &lt;code&gt;NullPointerException&lt;/code&gt;. Or we run our unit tests and see exactly what test failed.&lt;/p&gt;

&lt;p&gt;Autonomous AI agents don’t work like that. An agent doesn’t execute a single static function; it embarks on a multi-step journey toward a goal. In AI engineering, that journey is known as the agent’s &lt;strong&gt;trajectory&lt;/strong&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;What is an Agent Trajectory?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
An agent trajectory is the complete, chronological sequence of intermediate states, reasoning steps, tool calls, environment responses, and course corrections the model takes from its initial prompt to the final output.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Think of it as a state machine where every step consists of a continuous route:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fszozg3kark94i3od68yo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fszozg3kark94i3od68yo.png" alt="Agent Trajectory" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For example, a four-turn trajectory might look like:&lt;br&gt;&lt;br&gt;
&lt;code&gt;Turn 1: Read SPEC.md&lt;/code&gt; → &lt;code&gt;Turn 2: Run pytest (fails)&lt;/code&gt; → &lt;code&gt;Turn 3: Edit code&lt;/code&gt; → &lt;code&gt;Turn 4: Re-run test (passes)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;When an agent fails, it rarely crashes with a fatal error. Instead, it suffers from &lt;strong&gt;trajectory drift&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Did it misinterpret a requirement back on turn 2?&lt;/li&gt;
&lt;li&gt;Did a sandboxed CLI return an ambiguous warning on turn 4 that poisoned the agent’s reasoning on turn 5?&lt;/li&gt;
&lt;li&gt;Did the model get stuck in a “thrashing loop” between turns 8 and 12, fruitlessly editing the same file back and forth?&lt;/li&gt;
&lt;li&gt;Did it choose a blunt command-line tool when an exact MCP endpoint was sitting right in its prompt?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Without trajectory observability, you are left staring at a vague final apology from the model, completely blind to where the journey went off the rails.&lt;/p&gt;

&lt;p&gt;A robust developer harness treats trajectory monitoring as a first-class citizen:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Step-Level Execution Traces:&lt;/strong&gt; The harness records structured session transcripts (such as JSONL traces) capturing the exact prompt payload, the model’s internal thinking traces, the precise tool arguments sent, and the raw &lt;code&gt;stdout&lt;/code&gt;/&lt;code&gt;stderr&lt;/code&gt; returned by the sandbox.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Context &amp;amp; Token Telemetry:&lt;/strong&gt; Real-time instrumentation tracking how context size inflates turn by turn. This lets you pinpoint runaway token spikes, prompt cache hit rates, and the exact cost of each iteration before a loop drains your budget.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enterprise OpenTelemetry &amp;amp; Cloud Trace:&lt;/strong&gt; When moving from local IDE harnesses to cloud-hosted agents (e.g. running Google ADK agents on Cloud Run or the Google Agent Platform), the harness exports distributed traces into &lt;strong&gt;Google Cloud Trace&lt;/strong&gt; and structured events into &lt;strong&gt;Cloud Logging&lt;/strong&gt;. Every tool call becomes an inspectable trace span.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;When you can inspect the full trajectory, debugging ceases to be guesswork. You can conduct a forensic post-mortem on any failed run and immediately determine: &lt;em&gt;Did the model experience a reasoning failure, or did my harness fail to provide the right deterministic rail?&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary &amp;amp; What's Next: Firing Up the Engine
&lt;/h2&gt;

&lt;p&gt;We have &lt;em&gt;shifted left&lt;/em&gt; and engineered the deterministic foundations: living rules, version-controlled state, curated tools, progressive skill disclosure, plugin packaging, sandboxed boundaries, and execution traces. We have built the race car chassis.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Now, how does work actually get done?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In &lt;strong&gt;Part 2&lt;/strong&gt;, we fire up the dynamic runtime engine inside the harness: &lt;strong&gt;Loop Engineering&lt;/strong&gt;. We will explore:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Why autonomous feedback loops crush single-pass generation.&lt;/li&gt;
&lt;li&gt;The core mechanical components of an engineered developer loop.&lt;/li&gt;
&lt;li&gt;The Ratchet Principle.&lt;/li&gt;
&lt;li&gt;The Diagnostic Rule of Thumb: &lt;em&gt;Is it a Loop bug or a Harness bug?&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Designing Evaluation Rubrics (combining traditional tests with LLM goal evaluation and deterministic tool trajectory verification).&lt;/li&gt;
&lt;li&gt;A complete, turn-by-turn trace of an autonomous agent self-correcting in real time.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;loopy&lt;/code&gt; skill, and the Loop Library.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;👉 &lt;strong&gt;Continue to Part 2: Loop Engineering in the Harness: Autonomous, Self-Correcting Systems (Coming Soon)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;See you there!&lt;/p&gt;

&lt;h2&gt;
  
  
  Before You Go
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Please share&lt;/strong&gt; 📢 this with anyone that you think will be interested. It might help them, and it really helps me!&lt;/li&gt;
&lt;li&gt;Please &lt;strong&gt;give me loads of claps&lt;/strong&gt;! 👏 (Just hold down the clap button.)&lt;/li&gt;
&lt;li&gt;Please &lt;strong&gt;leave a comment&lt;/strong&gt; 💬. Interaction is good!&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Add a star&lt;/strong&gt; ⭐ on my repos!&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Follow&lt;/strong&gt; 👉 and &lt;strong&gt;subscribe&lt;/strong&gt; 🔔, so you don’t miss my content.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  References and Useful Links
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Harness &amp;amp; Ecosystem
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://cloud.google.com/discover/agent-harness?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;&lt;em&gt;What is an agent harness?&lt;/em&gt; | Google Cloud Discover&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=W9BX0jyzd2k" rel="noopener noreferrer"&gt;&lt;em&gt;What is an Agentic Harness?&lt;/em&gt; (Google Cloud Tech)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=F8EZJAm9iO8" rel="noopener noreferrer"&gt;&lt;em&gt;Harness Engineering Explained: Inside the Stack Behind Antigravity, Claude Code &amp;amp; Cursor&lt;/em&gt; (The Agent Factory with Ryan Lopopolo on Google Cloud Tech)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/google-cloud/the-ai-native-developer-experience-part-2-harness-engineering-with-google-antigravity-7fb72dab243f" rel="noopener noreferrer"&gt;&lt;em&gt;The AI-Native Developer Experience, Part 2: Harness Engineering with Google Antigravity&lt;/em&gt; by Jaroslav Pantsjoha (JP)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.builder.io/blog/de-slop-ai-generated-codebase" rel="noopener noreferrer"&gt;&lt;em&gt;How to De-Slop an AI-Generated Codebase&lt;/em&gt; by Alice Moore | Builder.io&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/google/skills/tree/main/plugins/cloud/google-cloud-developer" rel="noopener noreferrer"&gt;google-cloud-developer plugin on GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/google/agents-cli" rel="noopener noreferrer"&gt;&lt;em&gt;Google Agents CLI&lt;/em&gt; on GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/vercel-labs/skills" rel="noopener noreferrer"&gt;&lt;em&gt;Vercel Skills CLI&lt;/em&gt; on GitHub&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Dazbo's Related Articles
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.to/gde/skills-sprawl-when-too-much-of-a-good-thing-confuses-your-ai-agent-4nij"&gt;&lt;em&gt;Skills Sprawl: When Too Much of a Good Thing Confuses Your AI Agent&lt;/em&gt; by Dazbo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/gde/dialling-our-agents-to-11-agent-skills-you-need-to-be-using-2o2k"&gt;&lt;em&gt;Dialling Our Agents to 11: Agent Skills You Need to be Using!&lt;/em&gt; by Dazbo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/gde/dialling-our-agents-to-11-my-favourite-mcp-servers-3hbm"&gt;&lt;em&gt;Dialling Our Agents to 11: My Favourite MCP Servers&lt;/em&gt; by Dazbo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dazbo.co.uk" rel="noopener noreferrer"&gt;&lt;em&gt;Dazbo’s Portfolio&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>contextengineering</category>
      <category>agentskills</category>
      <category>agenticai</category>
      <category>mcps</category>
    </item>
    <item>
      <title>Meet the Antigravity Extension: Gemini Code Assist on Steroids, in Whatever IDE You Love</title>
      <dc:creator>Darren "Dazbo" Lester</dc:creator>
      <pubDate>Fri, 21 Aug 2026 01:11:12 +0000</pubDate>
      <link>https://dev.to/gde/meet-the-antigravity-extension-gemini-code-assist-on-steroids-in-whatever-ide-you-love-4p1n</link>
      <guid>https://dev.to/gde/meet-the-antigravity-extension-gemini-code-assist-on-steroids-in-whatever-ide-you-love-4p1n</guid>
      <description>&lt;p&gt;Google Antigravity (or Agy) was first launched as an agent-first development environment in late 2025. Then, in May 2026, Google released the new Antigravity suite, comprising four &lt;em&gt;surfaces&lt;/em&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbxlsl4isnnbg611mth0f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbxlsl4isnnbg611mth0f.png" alt="Antigravity surfaces" width="800" height="371"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Antigravity 2.0&lt;/strong&gt; — The agent-first, intent-driven surface. For those who care about the outcomes, but not necessarily the code. It’s the modern agentic environment for &lt;em&gt;builders&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Antigravity IDE&lt;/strong&gt; — The familiar IDE (the IDE itself is a fork of VS Code), but with all the smarts of the Antigravity harness built-in.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Antigravity CLI&lt;/strong&gt; — The terminal user interface (TUI) experience. This replaced the very awesome &lt;strong&gt;Gemini CLI&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Antigravity SDK&lt;/strong&gt; — For developers who want to harness the full power of Antigravity programmatically.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;All these surfaces use the same Antigravity &lt;em&gt;harness&lt;/em&gt;. They give you capabilities such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Advanced multi-stage reasoning, using the latest Gemini models.&lt;/li&gt;
&lt;li&gt;Full repo refactoring.&lt;/li&gt;
&lt;li&gt;Planning, execution and evidencing.&lt;/li&gt;
&lt;li&gt;Agent loops and subagent swarm orchestration.&lt;/li&gt;
&lt;li&gt;Integration with file system and shell environment.&lt;/li&gt;
&lt;li&gt;Multiple useful built-in commands and subagents.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At the same time, Google announced that both &lt;a href="https://docs.cloud.google.com/gemini/docs/codeassist/overview?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;Gemini Code Assist&lt;/a&gt; and &lt;a href="https://geminicli.com/" rel="noopener noreferrer"&gt;Gemini CLI&lt;/a&gt; were &lt;a href="https://developers.googleblog.com/an-important-update-transitioning-gemini-cli-to-antigravity-cli/?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco#important-timeline-for-consumers" rel="noopener noreferrer"&gt;end-of-life&lt;/a&gt;. And indeed, unless you happened to run inside an organisation that had paid for enterprise licenses, these products got turned off in June 2026.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fm3s6nxk18kftcknpehzm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fm3s6nxk18kftcknpehzm.png" alt="Gemini CLI — end-of-life" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Worry
&lt;/h2&gt;

&lt;p&gt;Gemini CLI was great. I was gutted to see it go. But &lt;a href="https://antigravity.google/product/antigravity-cli?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;Antigravity CLI&lt;/a&gt; was a worthy replacement, and it was immediately available. So we made the switch, and we were happy.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;But what about the death of Gemini Code Assist?&lt;/strong&gt; If you’re not familiar with this tool: it was the Gemini agent that you could install as an extension into your favourite IDE, like VS Code or IntelliJ. The agent ran in a side panel, fully-integrated with your IDE.&lt;/p&gt;

&lt;p&gt;Then Google told us:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;“Gemini Code Assist is dead. But don’t worry. For all you coders out there, just switch to Antigravity IDE. It feels like VS Code and you get the Gemini Code Assist experience — on steroids.”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;(They may not have actually used these words.)&lt;/p&gt;

&lt;p&gt;And this is exactly what I did. I briefly mourned VS Code, and then went all-in on Agy IDE.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fzvr5u0cef6vv2rq8cdu1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fzvr5u0cef6vv2rq8cdu1.png" alt="All in on Agy IDE" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But I was rather vocal in sharing my thoughts with some influential folk at Google.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frkxd4n4huxiocc36eh7n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frkxd4n4huxiocc36eh7n.png" alt="Sharing opinions" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;My thoughts being:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Some folks — like me — were happy to make the switch. But there are tens of millions of developers who &lt;strong&gt;WILL NOT give up their favourite IDE&lt;/strong&gt;. So, if you tell them: &lt;em&gt;“Switch to Agy, or you stay where you are, but with no Gemini”&lt;/em&gt;, then they’re gonna say: &lt;em&gt;“Okay. I’ll go with option 2.”&lt;/em&gt; To me, that’s a lose-lose situation.&lt;/li&gt;
&lt;li&gt;Some enterprises are pretty strict about their approved development environments and ecosystems. And — for reasons — they can be SOOOOO SLOW at adopting new things.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4xxvax5ha1ligc0f6tug.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4xxvax5ha1ligc0f6tug.png" alt="So slow" width="800" height="517"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The TL;DR — there was no viable path for developers who wanted to evolve from the Gemini Code Assist experience, but stay with their favourite IDE.&lt;/p&gt;

&lt;h2&gt;
  
  
  Until Now
&lt;/h2&gt;

&lt;p&gt;Today (August 20, as I write this), Google launched the Antigravity extension for IDEs! You can check out the official Google release blog, &lt;a href="https://antigravity.google/blog/antigravity-ide-extensions?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;here&lt;/a&gt;. Right now, there are Agy extensions for VS Code, Visual Studio, IntelliJ IDEs, and Zed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;I can’t tell you how stoked I am about this announcement!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;What is it? Well, think of it as a replacement for the Gemini Code Assist extension. It’s Gemini Code Assist, but pumped with steroids and caffeine. It’s all the cool Agy harness capabilities we’ve come to love in Antigravity 2.0, Antigravity CLI and Antigravity IDE, but now packaged as an extension.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgwiqdq4notxw3xb3rnzw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgwiqdq4notxw3xb3rnzw.png" alt="Antigravity extension" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So, as of tonight, I’ve switched back to VS Code!&lt;/p&gt;

&lt;h2&gt;
  
  
  Install the Extension
&lt;/h2&gt;

&lt;p&gt;Let’s install it! I’m using VS Code, so I’m installing &lt;a href="https://marketplace.visualstudio.com/items?itemName=Google.google-antigravity" rel="noopener noreferrer"&gt;this extension&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you happen to go looking for “Google Antigravity” in the VS Code Marketplace, be sure to install this one by &lt;code&gt;google.com&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2rdy533l00r185i5m20a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2rdy533l00r185i5m20a.png" alt="Installing Antigravity extension" width="799" height="605"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When you open the extension, you’ll see this in VS Code:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgrylix9mq9cndv0bs0d6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgrylix9mq9cndv0bs0d6.png" alt="Install in VS Code" width="800" height="459"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click &lt;strong&gt;Install&lt;/strong&gt;, and you’ll be asked to sign-in to Google:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkqdi1onnrt4rc374w4uc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkqdi1onnrt4rc374w4uc.png" alt="Sign-in" width="800" height="856"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And you’ll be asked if you want to install any of the ready-made &lt;strong&gt;plugins&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fl0qtakd92xge2wrawkeu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fl0qtakd92xge2wrawkeu.png" alt="Agy plugins" width="800" height="926"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And that’s it!&lt;/p&gt;

&lt;p&gt;It took about 20 seconds, and now the Antigravity extension is working in my VS Code!&lt;/p&gt;

&lt;h2&gt;
  
  
  Take It For a Spin
&lt;/h2&gt;

&lt;p&gt;I wondered if all my existing agent skills and MCP servers would be working. So I asked it: &lt;em&gt;“Install my Gemini code reviewer”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;It immediately found and activated my &lt;a href="https://github.com/derailed-dash/dazbo-agent-skills" rel="noopener noreferrer"&gt;&lt;code&gt;install-gemini-code-review-action&lt;/code&gt; skill&lt;/a&gt; and used it to install my &lt;a href="https://github.com/derailed-dash/gemini-review-action" rel="noopener noreferrer"&gt;Gemini Code Review Action&lt;/a&gt; into the local repo. It then asked for permission to commit these changes push them to GitHub. I gave Agy permission, and it went ahead and pushed.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F58etovduq1kw93k7rn26.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F58etovduq1kw93k7rn26.png" alt="Activated skills and MCPs" width="745" height="1363"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So this proved that my existing skills were immediately discovered, activated and used, and that it was able to use my GitHub MCP to perform the commit and push. Nice!&lt;/p&gt;

&lt;h2&gt;
  
  
  Models
&lt;/h2&gt;

&lt;p&gt;We can see the models that are available:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fues6nivwa77i9spiad76.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fues6nivwa77i9spiad76.png" alt="Model selection in Agy" width="800" height="813"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And we can see more model and Antigravity extension &lt;strong&gt;settings&lt;/strong&gt; here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fz57zyhg4kge0uaotxeei.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fz57zyhg4kge0uaotxeei.png" alt="Settings" width="800" height="558"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(I love the fact that next to my “AI Ultra” subscription is an “Upgrade” button. Seriously? Lol!)&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Plugins Created Some Skills Duplication
&lt;/h2&gt;

&lt;p&gt;The newly installed plugins resulted in duplication of some skills I had previously installed in my &lt;code&gt;~/.gemini/config/skills&lt;/code&gt; folder. So I said to Antigravity: &lt;em&gt;"Let's do a skills optimisation run."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;It went ahead and activated my &lt;a href="https://github.com/derailed-dash/dazbo-agent-skills" rel="noopener noreferrer"&gt;&lt;code&gt;organise-agent-skills&lt;/code&gt;&lt;/a&gt;. The skill made a number of recommendations which I implemented. The results looked like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7garfe6rp5rbx7bpe7y7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7garfe6rp5rbx7bpe7y7.png" alt="Skills optimised" width="800" height="820"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Wow!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;29 duplicated skills deleted.&lt;/li&gt;
&lt;li&gt;56 “sub-skills” set to excluded, because they are managed by their parent skills.&lt;/li&gt;
&lt;li&gt;68% reduction in token overhead!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Great, so our skills are back to running nice and lean.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Nice View of Token Usage
&lt;/h2&gt;

&lt;p&gt;Whilst we’re talking about token optimisation, I stumbled across this “Customization” page in the Agy extension settings:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhcfbtb1pgdwml611vvit.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhcfbtb1pgdwml611vvit.png" alt="Agy Settings — Customizations" width="800" height="507"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is nice view that how much of your “customization budget” is being consumed by all your &lt;code&gt;GEMINI.md&lt;/code&gt; (or &lt;code&gt;AGENTS.md&lt;/code&gt;), your skills, and your MCP tools. What’s quite interesting to note is that Agy will automatically start truncating if you exceed this budget. So you might suddenly find that your skills are being ignored, for example. This is another good reason to optimise your install skills and MCP servers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Things Not Working
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Browser Subagent
&lt;/h3&gt;

&lt;p&gt;The first thing I struggled with is the built-in browser subagent. I couldn’t get this to browse web pages for me, even after I enabled the remote debugging in Chrome. I did expect this. My VS Code is running in Windows, but connected to my repos in WSL. This has typically been a problem area for browser subagents. Maybe I’ll be able to get it working, if I put in a bit of work. But tonight… I’m far too tired!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(I should mention: this issue is only for WSL users. 4 out of 5 developers won’t be affected by this.)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;On the plus side, I was able to remote control the browser with my existing &lt;a href="https://browsermcp.io/" rel="noopener noreferrer"&gt;BrowserMCP&lt;/a&gt; configuration. No changes required.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvf901jdnpbnvgq92xa3f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvf901jdnpbnvgq92xa3f.png" alt="Browsing with BrowserMCP extension" width="800" height="767"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Antigravity In-Line Complete and Tab Features
&lt;/h3&gt;

&lt;p&gt;One thing I really love about Antigravity IDE is the real-time suggestions and edits you can make in the editor window.&lt;/p&gt;

&lt;p&gt;For example: if I were to change one instance of &lt;em&gt;“We did something”&lt;/em&gt; to &lt;em&gt;“I did something”&lt;/em&gt;, then Antigravity IDE allows me to update all remaining instances in a context-aware way, just by pressing tab.&lt;/p&gt;

&lt;p&gt;This feature is not currently working for me with the Agy extension in VS Code. So it’s possible my configuration isn’t correct, or this feature hasn’t been implemented in the extension yet. But this is only day 1!&lt;/p&gt;

&lt;h2&gt;
  
  
  What Does This Mean for Agy IDE?
&lt;/h2&gt;

&lt;p&gt;Within hours of the extension arriving, many folks have been asking me, &lt;em&gt;“What does this mean for Agy IDE? Will Google kill it?”&lt;/em&gt; It’s a question I’ve been asking my friends at Google for a little while.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Nobody&lt;/em&gt; has explicitly told me that Google &lt;em&gt;will&lt;/em&gt; kill Agy IDE. But my thoughts are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If the Agy extension provides the full Agy harness experience in all the major IDEs, what’s the &lt;em&gt;point&lt;/em&gt; in having a separate IDE that looks a lot like VS Code?&lt;/li&gt;
&lt;li&gt;Why would Google want to maintain the “IDE” components of Agy IDE, when these are essentially just a fork of VS Code anyway? That’s a lot of work.&lt;/li&gt;
&lt;li&gt;Lastly, take a look at the &lt;a href="https://antigravity.google/changelog" rel="noopener noreferrer"&gt;release notes&lt;/a&gt; for Agy 2.0, Agy CLI, and Agy IDE. The relative sparsity (is that a word?) of Agy IDE patches is telling.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Personally, I think the writing is on the wall.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrap-Up
&lt;/h2&gt;

&lt;p&gt;I’m so happy this Agy extension has arrived. Now any developer can use the extremely capable Antigravity harness from their IDE of choice. It gives a viable migration path for those who were using Gemini Code Assist before.&lt;/p&gt;

&lt;p&gt;For me, the install experience was totally painless, and everything just worked out-of-the-box. (Well, almost everything. But I can wait for the other things.) The agent is responsive and works. And it picked up all my existing configuration.&lt;/p&gt;

&lt;p&gt;That’s it! Go forth and use Antigravity in your favourite editor!&lt;/p&gt;

&lt;h2&gt;
  
  
  Before You Go
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Please share&lt;/strong&gt; 📢 this with anyone that you think will be interested. It might help them, and it really helps me!&lt;/li&gt;
&lt;li&gt;Please &lt;strong&gt;give me loads of claps&lt;/strong&gt;! 👏 (Just hold down the clap button.)&lt;/li&gt;
&lt;li&gt;Please &lt;strong&gt;leave a comment&lt;/strong&gt; 💬. Interaction is good!&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Add a star&lt;/strong&gt; ⭐ on my repos!&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Follow&lt;/strong&gt; 👉 and &lt;strong&gt;subscribe&lt;/strong&gt; 🔔, so you don’t miss my content.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  References and Useful Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dazbo.co.uk/" rel="noopener noreferrer"&gt;Dazbo’s Portfolio&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://antigravity.google/?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;Google Antigravity Official Site&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://antigravity.google/blog/antigravity-ide-extensions?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;Google Antigravity IDE Extensions Announcement&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://marketplace.visualstudio.com/items?itemName=Google.google-antigravity" rel="noopener noreferrer"&gt;Google Antigravity Extension on the Visual Studio Marketplace&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/derailed-dash/dazbo-agent-skills" rel="noopener noreferrer"&gt;Dazbo’s Agent Skills Repository&lt;/a&gt; — if you like it, please add a star!&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/derailed-dash/gemini-review-action" rel="noopener noreferrer"&gt;Dazbo’s Gemini Code Review Action&lt;/a&gt; — if you like it, please add a star!&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>antigravityextension</category>
      <category>googleantigravity</category>
      <category>vscode</category>
      <category>gemini</category>
    </item>
    <item>
      <title>Skills Sprawl: When Too Much of a Good Thing Confuses Your AI Agent</title>
      <dc:creator>Darren "Dazbo" Lester</dc:creator>
      <pubDate>Mon, 17 Aug 2026 10:13:26 +0000</pubDate>
      <link>https://dev.to/gde/skills-sprawl-when-too-much-of-a-good-thing-confuses-your-ai-agent-4nij</link>
      <guid>https://dev.to/gde/skills-sprawl-when-too-much-of-a-good-thing-confuses-your-ai-agent-4nij</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;In this post, we're going to look at the problem of &lt;strong&gt;Skills Sprawl&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;What happens if you have too many skills?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;We'll understand LLM decision fatigue and tool selection accuracy, inspect the mechanics of excluded vs inactive skills in Google Antigravity, and see how pruning your setup can make your agent smarter and save hundreds of thousands of tokens per session.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjmzizl4hniw1mur7acgb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjmzizl4hniw1mur7acgb.png" alt="Special set of skills" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Skills Context (It's a Sort of Pun...)
&lt;/h2&gt;

&lt;p&gt;Everyone knows that &lt;em&gt;agent skills&lt;/em&gt; are awesome. If you don't, then:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Where have you been?&lt;/li&gt;
&lt;li&gt;You're in for a treat!&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In some of my previous posts I've talked about how skills act as &lt;strong&gt;on-demand power-ups&lt;/strong&gt; for our agents. We use them to provide knowledge, rules, and workflows to do things the agent (or more specifically, the model) didn't otherwise know how to do effectively. &lt;/p&gt;

&lt;p&gt;You might have seen me compare this to how Neo loads his skills in the Matrix. &lt;em&gt;"I know Kung Fu!"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This &lt;em&gt;just-in-time knowledge&lt;/em&gt; provides a number of advantages to our agents:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;They know how to do a thing well.&lt;/li&gt;
&lt;li&gt;They don't hallucinate the things they don't know about.&lt;/li&gt;
&lt;li&gt;They don't have to experiment and course-correct; consequently, they're more likely to succeed the first time, and they do it with a minimum number of tokens consumed.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In short: &lt;strong&gt;faster, cheaper, and more reliable&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Quick aside: when I say &lt;em&gt;agent&lt;/em&gt;, I'm typically talking about your agentic partner in development crime, like &lt;a href="https://antigravity.google/?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;Google Antigravity&lt;/a&gt;, Claude Code, or whatever. But when you're building your own agentic solutions, you can use skills in exactly the same way. For example, check out my blog &lt;a href="https://medium.com/google-cloud/automated-github-code-reviewsusing-google-gemini-7b4d027b3092?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;Automated GitHub Code Reviews Using Google Gemini&lt;/a&gt;, where I've built an agentic PR review solution that leverages skills.&lt;/p&gt;

&lt;h2&gt;
  
  
  Overview of Progressive Disclosure
&lt;/h2&gt;

&lt;p&gt;Skills use a cool mechanism called &lt;strong&gt;progressive disclosure&lt;/strong&gt; to load on-demand.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fp203vadwlsxw7uiedtki.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fp203vadwlsxw7uiedtki.png" alt="Progressive Disclosure in Agent Skills" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's quickly recap this mechanism:&lt;/p&gt;

&lt;h3&gt;
  
  
  Level 1: Metadata (Frontmatter)
&lt;/h3&gt;

&lt;p&gt;When your agent starts up, it reads &lt;strong&gt;the frontmatter&lt;/strong&gt; - and &lt;strong&gt;only the frontmatter&lt;/strong&gt; - of &lt;strong&gt;every installed skill&lt;/strong&gt; in your global configuration and workspace. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;By the way, if you don't know where these skills should be placed, or you don't know the difference between global and workspace locations, check out my earlier blog: &lt;a href="https://medium.com/google-cloud/confused-about-where-to-put-your-agent-skills-ea778f3c64f3?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;Confused About Where to Put Your Agent Skills?&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The frontmatter is simply the descriptive YAML at the top of each skill which contains the skill name, a description (what it does and when it should be used), and any additional useful metadata (such as what tools it might use, author, etc). &lt;/p&gt;

&lt;p&gt;For example, this is from my &lt;code&gt;maintaining-core-documentation&lt;/code&gt; skill:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;maintaining-core-documentation&lt;/span&gt;
&lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
  &lt;span class="s"&gt;Creates, maintains, and synchronises core project documentation (README, TODO, DESIGN, Architecture, Testing, Deployment). Use when the user needs to write, update, or structure project documentation based on codebase changes, or whenever asked to perform documentation reviews or updates.&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;author&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Darren "Dazbo" Lester&lt;/span&gt;
  &lt;span class="na"&gt;repository&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://github.com/derailed-dash/dazbo-agent-skills&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Crucially, this frontmatter section is &lt;em&gt;tiny&lt;/em&gt;. So even though the agent reads it up-front, it consumes very few tokens. Typically fewer than 100 tokens per skill.&lt;/p&gt;

&lt;p&gt;The agent now has a mental model of all the skills that are available to it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Level 2: Instructions Loading (On-Demand)
&lt;/h3&gt;

&lt;p&gt;When the agent is asked to do a task that one of these skills might be useful for, the model selects the skill (based on the frontmatter), and then &lt;strong&gt;activates&lt;/strong&gt; it. When this happens, the agent reads the &lt;code&gt;SKILL.md&lt;/code&gt; body into context.&lt;/p&gt;

&lt;p&gt;This will typically add several hundred, if not thousands of tokens.&lt;/p&gt;

&lt;h3&gt;
  
  
  Level 3: Resources and Code (As Needed)
&lt;/h3&gt;

&lt;p&gt;Some skills may package additional resources, such as scripts, reference documents, or other assets. For example, my &lt;code&gt;maintaining-core-documentation&lt;/code&gt; skill has a &lt;code&gt;references&lt;/code&gt; subdirectory with several document template files.&lt;/p&gt;

&lt;p&gt;These assets are only loaded as needed.&lt;/p&gt;

&lt;h3&gt;
  
  
  How This Helps
&lt;/h3&gt;

&lt;p&gt;When we have skills, we don't need to include massive quantities of instructions in our global &lt;code&gt;GEMINI.md&lt;/code&gt; or &lt;code&gt;AGENTS.md&lt;/code&gt; files. Instead, all this knowledge is packaged into individual, self-contained, portable, on-demand units of knowledge.&lt;/p&gt;

&lt;p&gt;It is an elegant, modular pattern that massively reduces your token consumption.&lt;/p&gt;

&lt;h2&gt;
  
  
  But Can You Have Too Much of a Good Thing?
&lt;/h2&gt;

&lt;p&gt;There's no shortage of skills out there! You can use a public hub like &lt;a href="https://skills.sh/" rel="noopener noreferrer"&gt;skills.sh&lt;/a&gt; to find just about any skill you need. And, of course, you can create your own.&lt;/p&gt;

&lt;p&gt;Check out my blog &lt;a href="https://dev.to/gde/dialling-our-agents-to-11-agent-skills-you-need-to-be-using-2o2k"&gt;&lt;em&gt;Dialling Our Agents to 11: Agent Skills You Need to be Using!&lt;/em&gt;&lt;/a&gt;, where I list some of my favourite skills.&lt;/p&gt;

&lt;p&gt;The problem is... You end up &lt;em&gt;collecting.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flx5l2s5v8vrisigi47ok.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flx5l2s5v8vrisigi47ok.png" alt="The Museum of Obscure Digital Crafts and Skills" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I recently asked Antigravity to tell me how many skills I have. (I have sarcasm dialled up...)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Well, Dazbo, according to my context window — which is currently groaning under the crushing weight of your digital hoard — you currently have a staggering 170 skills installed.

Because obviously, why settle for a sleek, efficient setup when you can force your AI assistant to lug around the instruction manual for every obscure file converter, niche API, and hypothetical cloud deployment scenario known to humanity?

Truly, nothing says 'peak productivity' quite like burning thousands of tokens before we've even started speaking, just so I know how to format a Dev.to post while simultaneously standing by to orchestrate a multi-region Spanner failover.

I'm sure you'll be adding a 171st skill any second now — presumably one to help you manage the utter chaos of the first 170.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hilarious. 170. &lt;em&gt;Maybe I have too many.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The irony here is that Antigravity's last comment was spot on. I decided to &lt;strong&gt;build a skill to organise and optimise my skills!&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What's the Problem?
&lt;/h2&gt;

&lt;p&gt;As we've already covered: with progressive disclosure, the agent framework performs &lt;strong&gt;Tier 1 Discovery&lt;/strong&gt; on startup. It parses the frontmatter of &lt;strong&gt;every installed skill&lt;/strong&gt; and injects this straight into the system prompt.&lt;/p&gt;

&lt;p&gt;A well-crafted skill description needs enough context, trigger keywords, and intent markers for the LLM to know when to select it. (&lt;em&gt;"Use when..."&lt;/em&gt;) &lt;/p&gt;

&lt;p&gt;When I analysed my 170 skills, it turns out that my average skill frontmatter contained 103 tokens. Now let's do some quick maths:&lt;/p&gt;

&lt;p&gt;$$\text{170 active skills} \times 100\text{ tokens/description} = 17,000\text{ tokens}$$&lt;/p&gt;

&lt;p&gt;That means my agent is injecting &lt;strong&gt;17,000 tokens of system prompt overhead on every single turn&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If I'm engaged in a typical 30-turn pair-programming session:&lt;/p&gt;

&lt;p&gt;$$30\text{ turns} \times 17,000\text{ tokens} = 510,000\text{ tokens}$$&lt;/p&gt;

&lt;p&gt;That means I am burning an additional &lt;strong&gt;half a million tokens&lt;/strong&gt; just to re-read the index of my skill library over and over again.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;So what?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Let's look at some of the potential issues this creates:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Faf7xkpfxolzc9fa2jn0i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Faf7xkpfxolzc9fa2jn0i.png" alt="Three Major Impacts of AI Skill Sprawl" width="800" height="590"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Depending on your model choice, caching configuration, and AI subscription, there may be &lt;strong&gt;financial implications&lt;/strong&gt;. But it's likely to be small.&lt;/li&gt;
&lt;li&gt;It will definitely &lt;strong&gt;eat into your token limits&lt;/strong&gt;. Most models and plans have token limits and rate limits. Adding an extra 17K tokens per turn will definitely reduce how long it takes for you to exhaust your quota!&lt;/li&gt;
&lt;li&gt;Most importantly, &lt;strong&gt;it's confusing your model&lt;/strong&gt;. &lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Confusion-Nation
&lt;/h2&gt;

&lt;p&gt;Skills sprawl causes &lt;strong&gt;decision fatigue and skill selection accuracy degradation&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fw7j9a8k8egjr6opmss4a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fw7j9a8k8egjr6opmss4a.png" alt="Choice Ambiguity and Decision Fatigue in an Agent with 170 Skills" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When a model is presented with 170 potential skills simultaneously, it faces &lt;strong&gt;choice ambiguity&lt;/strong&gt;. Many skills will naturally have overlapping domain descriptions. For example, my 170 skills had overlaps in each of these areas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Content generation&lt;/li&gt;
&lt;li&gt;API guides (particularly for Gemini APIs and SDKs)&lt;/li&gt;
&lt;li&gt;Google products and services&lt;/li&gt;
&lt;li&gt;Test-driven development (TDD) and code reviews&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Does academic research back this up? Absolutely.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Empirical Evidence: Shortlist Depth and Selection Accuracy
&lt;/h3&gt;

&lt;p&gt;In a recent paper titled &lt;a href="https://arxiv.org/pdf/2605.24660" rel="noopener noreferrer"&gt;&lt;em&gt;“How Many Tools Should an LLM Agent See? A Chance-Corrected Answer”&lt;/em&gt;&lt;/a&gt; (&lt;em&gt;Repantis et al&lt;/em&gt;, May 2026), researchers evaluated LLM tool selection performance across 370 tools using the &lt;a href="https://gorilla.cs.berkeley.edu/leaderboard.html" rel="noopener noreferrer"&gt;&lt;strong&gt;Berkeley Function Calling Leaderboard (BFCL)&lt;/strong&gt;&lt;/a&gt; — the industry-standard benchmark for evaluating model tool-calling capabilities.&lt;/p&gt;

&lt;p&gt;They concluded:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;"Show too many tools and the model struggles to choose. Show too few and the correct tool may not appear."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;There is an important nuance here: if you only give a model 2 choices, it has a 50% chance of guessing correctly by pure luck. If you show it 50 choices, blind luck drops to 2%. &lt;/p&gt;

&lt;p&gt;When the researchers &lt;strong&gt;corrected for random chance&lt;/strong&gt; — measuring genuine model comprehension rather than lucky guesses — the impact of list size was striking:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Presenting an LLM with a crowded shortlist of &lt;strong&gt;50 tools&lt;/strong&gt; resulted in &lt;strong&gt;60.9% selection accuracy&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Scoping that shortlist down to &lt;strong&gt;~7 focused tools&lt;/strong&gt; boosted true accuracy to &lt;strong&gt;76.8%&lt;/strong&gt; (a 15.9 percentage-point leap in decision precision).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frdcap5u3ecqmop33ifcn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frdcap5u3ecqmop33ifcn.png" alt="LLM Tool Selection Accuracy vs Shortlist Depth" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Related benchmarks like &lt;a href="https://arxiv.org/abs/2310.03128" rel="noopener noreferrer"&gt;&lt;strong&gt;MetaTool&lt;/strong&gt;&lt;/a&gt; and &lt;a href="https://arxiv.org/abs/2307.16789" rel="noopener noreferrer"&gt;&lt;strong&gt;ToolBench&lt;/strong&gt;&lt;/a&gt; show the same results: as toolset sizes scale past 30–50 items without structured routing, error rates spike rapidly due to &lt;strong&gt;description collision&lt;/strong&gt; and noise. The model gets confused by keyword overlaps and either picks the wrong tool or hallucinates non-existent parameters.&lt;/p&gt;

&lt;p&gt;Okay, in this blog, I'm talking about skills, not tools. But the principle is the same. Too many skills lead to the same problems of confusion caused by description collision. &lt;/p&gt;

&lt;p&gt;We want:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Our agent to pick the right skills with a high degree of accuracy.&lt;/li&gt;
&lt;li&gt;To avoid burning unnecessary tokens.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;I need a way to optimise my installed skills!&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Do I Have So Many Skills?
&lt;/h2&gt;

&lt;p&gt;Before I start pruning my skills, I need to understand why I have so many.&lt;/p&gt;

&lt;p&gt;I went back and reviewed my Git history to trace how I got here. Here's what I discovered:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Google Cloud &amp;amp; AI knowledge:&lt;/strong&gt; Over 120 skills pulled from official Google repositories, including &lt;a href="https://github.com/google/skills" rel="noopener noreferrer"&gt;&lt;code&gt;google/skills&lt;/code&gt;&lt;/a&gt;, &lt;a href="https://github.com/google/agents-cli" rel="noopener noreferrer"&gt;&lt;code&gt;google/agents-cli&lt;/code&gt;&lt;/a&gt;, &lt;a href="https://github.com/google-gemini/gemini-skills" rel="noopener noreferrer"&gt;&lt;code&gt;google-gemini/gemini-skills&lt;/code&gt;&lt;/a&gt;, and &lt;a href="https://github.com/GoogleCloudPlatform/vertex-ai-creative-studio/tree/main/experiments/mcp-genmedia/skills" rel="noopener noreferrer"&gt;&lt;code&gt;GoogleCloudPlatform/vertex-ai-creative-studio&lt;/code&gt;&lt;/a&gt;. These include Google products and services (like BigQuery, Cloud SQL, GKE, Cloud Run), the Google Cloud Well-Architected Framework (WAF), Gemini and Google GenAI APIs and SDKs, and GenMedia.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dazbo Agent Skills:&lt;/strong&gt; Custom skills I wrote for &lt;a href="https://github.com/derailed-dash/dazbo-agent-skills" rel="noopener noreferrer"&gt;&lt;code&gt;derailed-dash/dazbo-agent-skills&lt;/code&gt;&lt;/a&gt; for documentation, blogging, security, installing automated PR code reviews, skill organisation, and deployment.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Core Software Engineering &amp;amp; Best Practices:&lt;/strong&gt; 25 skills adopted from Addy Osmani's &lt;a href="https://github.com/addyosmani/agent-skills" rel="noopener noreferrer"&gt;&lt;code&gt;addyosmani/agent-skills&lt;/code&gt;&lt;/a&gt; repository covering TDD, code review, debugging, interface design, context engineering, and software delivery workflows.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Research, Strategy &amp;amp; Technical Writing:&lt;/strong&gt; 5 specialised skills installed from Shubham Saboo's &lt;a href="https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/agent_skills" rel="noopener noreferrer"&gt;&lt;code&gt;shubhamsaboo/awesome-llm-apps&lt;/code&gt;&lt;/a&gt; repository (&lt;code&gt;deep-research&lt;/code&gt;, &lt;code&gt;fact-checker&lt;/code&gt;, &lt;code&gt;strategy-advisor&lt;/code&gt;, &lt;code&gt;technical-writer&lt;/code&gt;, &lt;code&gt;content-creator&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Specialised &amp;amp; Community Skills:&lt;/strong&gt; Niche skills sourced from specific community repositories, including &lt;a href="https://github.com/wshobson/agents" rel="noopener noreferrer"&gt;&lt;code&gt;wshobson/agents&lt;/code&gt;&lt;/a&gt; (&lt;code&gt;documentation-and-adrs&lt;/code&gt;, &lt;code&gt;interview-me&lt;/code&gt;), &lt;a href="https://github.com/coreyhaines31/marketingskills" rel="noopener noreferrer"&gt;&lt;code&gt;coreyhaines31/marketingskills&lt;/code&gt;&lt;/a&gt; (&lt;code&gt;seo-audit&lt;/code&gt;), &lt;a href="https://github.com/remotion-dev/skills" rel="noopener noreferrer"&gt;&lt;code&gt;remotion-dev/skills&lt;/code&gt;&lt;/a&gt; (&lt;code&gt;remotion-best-practices&lt;/code&gt;), and &lt;a href="https://github.com/vercel-labs/skills" rel="noopener noreferrer"&gt;&lt;code&gt;vercel-labs/skills&lt;/code&gt;&lt;/a&gt; (&lt;code&gt;find-skills&lt;/code&gt;).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here is the complete breakdown of the 170 skills I had installed, grouped by category and origin repository:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Group / Category&lt;/th&gt;
&lt;th&gt;Count&lt;/th&gt;
&lt;th&gt;Source Repository / Origin Link&lt;/th&gt;
&lt;th&gt;Summary of Included Skills&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Google Cloud Core Services &amp;amp; WAF&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;82&lt;/td&gt;
&lt;td&gt;&lt;a href="https://github.com/google/skills" rel="noopener noreferrer"&gt;&lt;code&gt;google/skills&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;GCP product &amp;amp; infrastructure guides (BigQuery, Cloud SQL, AlloyDB, GKE, Cloud Run, Firebase), Well-Architected Framework (WAF) pillars, networking, and developer APIs (Google Ads, Analytics, Mobile Ads).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Addy Osmani Engineering Workflows&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;25&lt;/td&gt;
&lt;td&gt;&lt;a href="https://github.com/addyosmani/agent-skills" rel="noopener noreferrer"&gt;&lt;code&gt;addyosmani/agent-skills&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;SDLC &amp;amp; software engineering workflow heuristics covering TDD, code review, debugging, context engineering, spec-driven development, and interface design (orchestrated via &lt;code&gt;using-agent-skills&lt;/code&gt;).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Google Agent Platform &amp;amp; ADK CLI&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;td&gt;&lt;a href="https://github.com/google/agents-cli" rel="noopener noreferrer"&gt;&lt;code&gt;google/agents-cli&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Agent Development Kit (ADK) CLI lifecycle tools (scaffolding, testing, evaluation, deployment, publishing) and server-managed Agent Platform resource handlers.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Specialised &amp;amp; Community Skills&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;14&lt;/td&gt;
&lt;td&gt;Various Community Sources&lt;/td&gt;
&lt;td&gt;Niche tools and community extensions including Dev.to formatting, Playwright browser testing, Remotion React video, SEO auditing, Python dependency management, and skill discovery (&lt;code&gt;find-skills&lt;/code&gt;).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Gemini API &amp;amp; GenAI SDKs&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;&lt;a href="https://github.com/google-gemini/gemini-skills" rel="noopener noreferrer"&gt;&lt;code&gt;google-gemini/gemini-skills&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Technical integration guides for the Gemini API (&lt;code&gt;google-genai&lt;/code&gt; SDK), multimodal streaming, Live API, NotebookLM auth, and server-managed interactions.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Google GenMedia &amp;amp; Creative Studio&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;&lt;a href="https://github.com/GoogleCloudPlatform/vertex-ai-creative-studio/tree/main/experiments/mcp-genmedia/skills" rel="noopener noreferrer"&gt;&lt;code&gt;vertex-ai-creative-studio&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Specialised role personas for multimedia production (audio engineering, image generation, video editing, voice direction, script producing, story generation).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Dazbo Custom Agent Skills&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;&lt;a href="https://github.com/derailed-dash/dazbo-agent-skills" rel="noopener noreferrer"&gt;&lt;code&gt;derailed-dash/dazbo-agent-skills&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Personal workflow automation for documentation maintenance, blog writing (&lt;code&gt;dazbo-content&lt;/code&gt;), secrets management (&lt;code&gt;git-crypt&lt;/code&gt;), UTM link tagging, PR review actions, skill organisation, and deployment.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Awesome LLM Apps (Research &amp;amp; Content)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;&lt;a href="https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/agent_skills" rel="noopener noreferrer"&gt;&lt;code&gt;shubhamsaboo/awesome-llm-apps&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Autonomous research, fact-checking, strategy advisory, and technical documentation generation workflows.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;TOTAL&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;170&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;So you can see how easy it is for your skills base to get out of hand! Especially if you work with Google Cloud and Google AI services like I do. It's super easy to install over 100 Google-related skills, by just following a few Google blog recommendations.&lt;/p&gt;

&lt;h2&gt;
  
  
  Next Question: Do I Need Them All?
&lt;/h2&gt;

&lt;p&gt;I asked Antigravity to read all of my skills in detail, and identify any areas of overlap and redundancy.&lt;/p&gt;

&lt;p&gt;There was a LOT of redundancy! We uncovered seven major categories of overlap, duplication, and inefficiency:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Exact Byte-for-Byte File &amp;amp; Naming Duplicates:&lt;/strong&gt; In &lt;a href="https://github.com/google/skills/tree/main/skills/cloud/gemini-agents-api" rel="noopener noreferrer"&gt;&lt;code&gt;google/skills&lt;/code&gt;&lt;/a&gt;, the skill directory &lt;code&gt;gemini-agents-api&lt;/code&gt; declared &lt;code&gt;name: gemini-managed-agents-api&lt;/code&gt; in its frontmatter. This directory vs. frontmatter mismatch caused installation tools to spawn two exact duplicate folders (&lt;code&gt;gemini-agents-api&lt;/code&gt; and &lt;code&gt;gemini-managed-agents-api&lt;/code&gt;) carrying 100% byte-for-byte identical content.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deprecated SDKs vs. Modern APIs:&lt;/strong&gt; Older skills still provided code snippets using the deprecated &lt;code&gt;google-generativeai&lt;/code&gt; package and obsolete model strings, directly contradicting modern &lt;code&gt;google-genai&lt;/code&gt; SDK standards and confusing the agent during code generation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;API Guide Overlaps &amp;amp; Fragmentation Across Repositories:&lt;/strong&gt; The &lt;code&gt;gemini-api&lt;/code&gt; skill in &lt;a href="https://github.com/google/skills/tree/main/skills/cloud/gemini-api" rel="noopener noreferrer"&gt;&lt;code&gt;google/skills&lt;/code&gt;&lt;/a&gt; (which exists as an enterprise Agent Platform guide) collided directly with &lt;code&gt;gemini-api-dev&lt;/code&gt; in &lt;a href="https://github.com/google-gemini/gemini-skills/tree/main/skills/gemini-api-dev" rel="noopener noreferrer"&gt;&lt;code&gt;google-gemini/gemini-skills&lt;/code&gt;&lt;/a&gt;. Installing across multiple Google repositories resulted in competing guides for the same underlying APIs (&lt;code&gt;gemini-api&lt;/code&gt;, &lt;code&gt;gemini-api-dev&lt;/code&gt;, &lt;code&gt;gemini-agents-api&lt;/code&gt;, &lt;code&gt;gemini-interactions-api&lt;/code&gt;, and &lt;code&gt;gemini-live-api-dev&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Irrelevant Domain Bundles (The Monolithic Repo Problem):&lt;/strong&gt; Pulling down the monolithic &lt;a href="https://github.com/google/skills" rel="noopener noreferrer"&gt;&lt;code&gt;google/skills&lt;/code&gt;&lt;/a&gt; repository imported mobile advertising suites (Android/iOS banner ads, Unity SDKs) that had zero relevance to cloud backend architecture and agent development.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hierarchical Sub-Skill Redundancies (The Meta-Skill Tax):&lt;/strong&gt; 25 individual SDLC skills from &lt;a href="https://github.com/addyosmani/agent-skills" rel="noopener noreferrer"&gt;&lt;code&gt;addyosmani/agent-skills&lt;/code&gt;&lt;/a&gt; (such as &lt;code&gt;test-driven-development&lt;/code&gt; and &lt;code&gt;code-review-and-quality&lt;/code&gt;) were loaded into system prompt context at startup, despite being child sub-skills already orchestrated on-demand by &lt;code&gt;using-agent-skills&lt;/code&gt;. Similarly, 20 sub-skills from &lt;a href="https://github.com/google/agents-cli" rel="noopener noreferrer"&gt;&lt;code&gt;google/agents-cli&lt;/code&gt;&lt;/a&gt; were loaded continuously rather than routed via &lt;code&gt;google-agents-cli-workflow&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tooling &amp;amp; MCP Surface Overlaps:&lt;/strong&gt; Standalone tools like the &lt;code&gt;adk-docs-mcp&lt;/code&gt; server were redundant because &lt;code&gt;google-developer-knowledge&lt;/code&gt; already indexes ADK documentation (&lt;code&gt;adk.dev&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Capability &amp;amp; Persona Redundancies:&lt;/strong&gt; &lt;code&gt;documentation-and-adrs&lt;/code&gt; (&lt;a href="https://github.com/addyosmani/agent-skills" rel="noopener noreferrer"&gt;&lt;code&gt;addyosmani/agent-skills&lt;/code&gt;&lt;/a&gt;) was a duplicate of &lt;code&gt;architecture-decision-records&lt;/code&gt; (&lt;a href="https://github.com/wshobson/agents" rel="noopener noreferrer"&gt;&lt;code&gt;wshobson/agents&lt;/code&gt;&lt;/a&gt;), while generic &lt;code&gt;content-creator&lt;/code&gt; (&lt;a href="https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/awesome_agent_skills" rel="noopener noreferrer"&gt;&lt;code&gt;shubhamsaboo/awesome-llm-apps&lt;/code&gt;&lt;/a&gt;) collided with my custom &lt;a href="https://github.com/derailed-dash/dazbo-agent-skills" rel="noopener noreferrer"&gt;&lt;code&gt;dazbo-content&lt;/code&gt;&lt;/a&gt; persona.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  What Else Did I Discover?
&lt;/h2&gt;

&lt;p&gt;Beyond the sheer volume of redundant skills, I made another cool discovery: &lt;strong&gt;many skill collections come with a "parent" Meta-Skill.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When you install a large collection of skills — such as Addy Osmani's engineering skills (&lt;a href="https://github.com/addyosmani/agent-skills" rel="noopener noreferrer"&gt;&lt;code&gt;addyosmani/agent-skills&lt;/code&gt;&lt;/a&gt;), or Google's 20 Agent Platform skills (&lt;a href="https://github.com/google/agents-cli" rel="noopener noreferrer"&gt;&lt;code&gt;google/agents-cli&lt;/code&gt;&lt;/a&gt;) — your instinct is to leave all 20 to 25 skills enabled in your workspace. I mean... &lt;em&gt;Why wouldn't you?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;However, these skill suites are designed to be &lt;strong&gt;hierarchical&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;addyosmani/agent-skills&lt;/code&gt;:&lt;/strong&gt; Orchestrated by the &lt;code&gt;using-agent-skills&lt;/code&gt; meta-skill.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Google ADK &amp;amp; Agent Platform:&lt;/strong&gt; Orchestrated by the &lt;code&gt;google-agents-cli-workflow&lt;/code&gt; meta-skill.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GCP Data Pipelines:&lt;/strong&gt; Orchestrated by the &lt;code&gt;gcp-data-pipelines&lt;/code&gt; meta-skill.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In each case, the parent meta-skill is supposed to work as a sort of skills index or decision tree. When a specific task comes in — such as writing unit tests or running a security audit — the parent meta-skill directs the agent to fetch and read &lt;em&gt;only&lt;/em&gt; the specific &lt;em&gt;child&lt;/em&gt; sub-skill from disk on demand.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9ue0lyme8b2bzh4zci3g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9ue0lyme8b2bzh4zci3g.png" alt="Parent Meta-Skill Routing Architecture" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Conclusion? &lt;strong&gt;We don't need to load the frontmatter of all the &lt;em&gt;child&lt;/em&gt; skills. We only need the parent skill!&lt;/strong&gt; In the examples above, I can easily replace nearly 50 skills with just 3 orchestration skills!&lt;/p&gt;

&lt;p&gt;So now I could implement a solution to organise my skills. The primary objectives:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Remove skills that are truly redundant.&lt;/li&gt;
&lt;li&gt;Prevent Level 1 skills loading (i.e. reading frontmatter into context) for skills that have parent meta-skills. For these, only pre-load the parent meta-skills.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Clarifying Skill States
&lt;/h2&gt;

&lt;p&gt;To design a lean agent workspace, we must be crystal clear on the three distinct states a skill can occupy throughout its lifecycle. They can be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Installed and inactive (discoverable).&lt;/li&gt;
&lt;li&gt;Installed and excluded.&lt;/li&gt;
&lt;li&gt;Activated.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's define these in more detail:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Installed and inactive (discoverable)&lt;/strong&gt;: These skills are present on disk and discoverable by our agent. When the agent (e.g. Antigravity) starts, their frontmatter is automatically read into context.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Installed and excluded&lt;/strong&gt;: These skills reside in your disk library but are &lt;em&gt;excluded&lt;/em&gt; from automatic Level 1 loading. For these, the agent does not automatically read their frontmatter and is therefore not &lt;em&gt;directly&lt;/em&gt; aware of them during your conversation with it. But because they are present on disk and available to the agent, they can still be explicitly activated.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Activated&lt;/strong&gt;: This is the runtime state when a skill's full &lt;code&gt;SKILL.md&lt;/code&gt; body has been loaded into the current turn context, i.e. Level 2 loading (and Level 3, where supporting files are present and appropriate).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Crucially, &lt;strong&gt;both &lt;em&gt;installed and inactive&lt;/em&gt; and &lt;em&gt;installed and excluded&lt;/em&gt; skills can transition into this &lt;em&gt;Activated&lt;/em&gt; state.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbsdsrap31wexgzsx7k97.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbsdsrap31wexgzsx7k97.png" alt="Agent Skill Lifecycle: States &amp;amp; Transitions" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Excluding Skills
&lt;/h2&gt;

&lt;p&gt;So now we know that a good optimisation strategy is to use exclusion to prevent a bunch of skills being loaded at startup into the "Installed and inactive" state.&lt;/p&gt;

&lt;p&gt;But how can we do this?&lt;/p&gt;

&lt;p&gt;In &lt;strong&gt;Google Antigravity&lt;/strong&gt;, global skill exclusions are managed via &lt;code&gt;~/.gemini/config/skills.json&lt;/code&gt; (or &lt;code&gt;.agents/skills.json&lt;/code&gt; for workspace-level skills).&lt;/p&gt;

&lt;p&gt;The native &lt;code&gt;exclude&lt;/code&gt; array accepts skill folder names. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"exclude"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"alloydb-basics"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"cloud-spanner-migrations"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"firebase-basics"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Any skill listed in the &lt;code&gt;exclude&lt;/code&gt; array is completely skipped during Tier 1 discovery. Its frontmatter is therefore &lt;strong&gt;not&lt;/strong&gt; injected into the system prompt, saving tokens instantly.&lt;/p&gt;

&lt;p&gt;So this is easy!&lt;/p&gt;

&lt;p&gt;But here's a cool trick. You can easily "un-exclude" a skill by prefixing its name with &lt;code&gt;//&lt;/code&gt; inside the quotes. This is useful because it allows us to re-enable up-front skill loading, without having to check our disk to find the skill and its name. &lt;/p&gt;

&lt;p&gt;So my approach is to always have &lt;em&gt;all&lt;/em&gt; my available skills in the &lt;code&gt;exclude&lt;/code&gt; list, but to comment-out the ones that need to be discovered automatically.&lt;/p&gt;

&lt;p&gt;Note: I have the &lt;code&gt;//&lt;/code&gt; &lt;em&gt;inside&lt;/em&gt; the quotes. Why? Because this is not valid JSON:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"exclude"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="s2"&gt;"alloydb-basics"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="s2"&gt;"find-skills"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"firebase-basics"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But this is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"exclude"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"//alloydb-basics"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"//find-skills"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"firebase-basics"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And because the &lt;code&gt;exclude&lt;/code&gt; list uses &lt;em&gt;exact&lt;/em&gt; string matching, you can use this &lt;code&gt;//&lt;/code&gt; trick to enable/exclude skills on the fly, without having to remove the skill from the &lt;code&gt;exclude&lt;/code&gt; list entirely. &lt;/p&gt;

&lt;p&gt;In the example above: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;alloydb-basics&lt;/code&gt; and &lt;code&gt;find-skills&lt;/code&gt; are &lt;em&gt;not&lt;/em&gt; excluded, so they are auto-discovered on startup and their frontmatter is loaded into context.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;firebase-basics&lt;/code&gt; &lt;em&gt;is&lt;/em&gt; excluded, so it is &lt;em&gt;not&lt;/em&gt; auto-discovered on startup and its frontmatter is &lt;em&gt;not&lt;/em&gt; loaded into context.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now we've got everything we need to implement a repeatable mechanism to organise and clean up our skills.&lt;/p&gt;

&lt;h2&gt;
  
  
  Irony and Guitars: I Made a Skill!
&lt;/h2&gt;

&lt;p&gt;Because: when you've got too many skills, you definitely need one more. (In this way, skills are a lot like guitars, or cats.)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fc2h2psk391ngciv9w5fy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fc2h2psk391ngciv9w5fy.png" alt="The N+1 Rule for Guitars (and Skills)" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Anyway, based on what I learned, I created a skill that:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Identifies duplicative skills and recommends complete removal of those that are redundant.&lt;/li&gt;
&lt;li&gt;Identifies which skills are orchestrated by a parent &lt;em&gt;meta-skill&lt;/em&gt; and &lt;em&gt;excludes&lt;/em&gt; the &lt;em&gt;child&lt;/em&gt; skills from automatic discovery.&lt;/li&gt;
&lt;li&gt;Identifies skills which look particularly niche or rarely used, and recommends excluding these also. They can always be included later, or even activated by explicitly asking the agent to do so.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let's see how it performs! After installing my skill, I said to Antigravity:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;"Optimise my skills please"&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Outcomes of Optimising
&lt;/h2&gt;

&lt;p&gt;My skill ran and presented this proposal summary table:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Baseline (Unoptimised)&lt;/th&gt;
&lt;th&gt;Proposed (Optimised)&lt;/th&gt;
&lt;th&gt;Delta / Savings&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Installed Skills Directories&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;170&lt;/td&gt;
&lt;td&gt;165&lt;/td&gt;
&lt;td&gt;-5 (-2.9%)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Installed &amp;amp; Discoverable Skills&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;170&lt;/td&gt;
&lt;td&gt;49&lt;/td&gt;
&lt;td&gt;-121 (-71.2%)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Installed &amp;amp; Excluded Skills&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;116&lt;/td&gt;
&lt;td&gt;+116&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Prompt Token Overhead&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;~17,000 tokens&lt;/td&gt;
&lt;td&gt;~3,350 tokens&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;-13,650 tokens (-80.3%)&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;It goes on to say:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;Upon your confirmation, I will execute the following steps:
&lt;span class="p"&gt;
1.&lt;/span&gt; &lt;span class="gs"&gt;**Retire Redundant Skills**&lt;/span&gt;: Delete the 5 redundant skill directories
   (&lt;span class="sb"&gt;`gemini-managed-agents-api`&lt;/span&gt;, &lt;span class="sb"&gt;`liveapi-service`&lt;/span&gt;, &lt;span class="sb"&gt;`documentation-and-adrs`&lt;/span&gt;, 
   &lt;span class="sb"&gt;`gemini-api-dev`&lt;/span&gt;, &lt;span class="sb"&gt;`gemini-live-api-dev`&lt;/span&gt;) from &lt;span class="sb"&gt;`~/.gemini/config/skills/`&lt;/span&gt;.
&lt;span class="p"&gt;2.&lt;/span&gt; &lt;span class="gs"&gt;**Generate Optimised `skills.json`**&lt;/span&gt;: Write the full-inventory &lt;span class="sb"&gt;`~/.gemini/config/skills.json`&lt;/span&gt; 
   with 49 active skills (&lt;span class="sb"&gt;`//`&lt;/span&gt; prefix) and 116 excluded skills.
&lt;span class="p"&gt;3.&lt;/span&gt; &lt;span class="gs"&gt;**Verify Context Footprint**&lt;/span&gt;: Re-audit the active skill prompt token overhead to confirm 
   successful reduction to ~3,350 tokens.
&lt;span class="p"&gt;
---&lt;/span&gt;
&lt;span class="gt"&gt;&amp;gt; [!IMPORTANT]&lt;/span&gt;
&lt;span class="gt"&gt;&amp;gt; **Mandatory Guardrail Confirmation**: In accordance with `organise-agent-skills` guardrails, please confirm if you would like me to proceed with deleting the 5 redundant skill directories and creating the optimised `~/.gemini/config/skills.json`.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By trimming back to a core of 49 active skills and delegating the rest to meta-skills and on-demand rules:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We slashed system prompt overhead by approximately 13,650 tokens; that's an &lt;strong&gt;80.3% reduction&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;We saved over &lt;strong&gt;400,000 tokens per pair-programming session&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Agent response latencies dropped noticeably.&lt;/li&gt;
&lt;li&gt;Tool selection precision increased because the agent was no longer fighting distractor noise from over 100 overlapping skill descriptions. Instead of having a mild existential crisis every turn trying to choose between five different Gemini SDK guides, the agent simply picks the right tool and gets on with the job.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffyukucn73r0k4e7lknvp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffyukucn73r0k4e7lknvp.png" alt="System Prompt Startup Overhead Comparison" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary &amp;amp; Conclusion
&lt;/h2&gt;

&lt;p&gt;Agent skills are awesome. They're so easy to find, install and use. But when we allow skills to sprawl unchecked, we start confusing our agents. This impacts accuracy, reliability, performance, and cost.&lt;/p&gt;

&lt;p&gt;So increasingly, we need a way to manage and optimise our skills. For this, I've done some work so you don't have to!&lt;/p&gt;

&lt;p&gt;Feel free to download my optimisation skill off-the-shelf:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Install all the Dazbo Agent Skills&lt;/span&gt;
npx skills add https://github.com/derailed-dash/dazbo-agent-skills

&lt;span class="c"&gt;# Install just the `Organise Agent Skills` skill&lt;/span&gt;
npx skills add https://github.com/derailed-dash/dazbo-agent-skills &lt;span class="nt"&gt;--skill&lt;/span&gt; organise-agent-skills
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or if you have the Vercel &lt;code&gt;find-skills&lt;/code&gt; skill installed, you can just ask your agent: &lt;/p&gt;

&lt;p&gt;&lt;em&gt;"Install &lt;code&gt;dazbo-agent-skills&lt;/code&gt; for me."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;So, that's it, folks. Go forth and optimise. If you find this skill useful, please give the &lt;a href="https://github.com/derailed-dash/dazbo-agent-skills" rel="noopener noreferrer"&gt;repo&lt;/a&gt; a star.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Have you experienced Skills Sprawl in your agentic environment? How many skills are currently active in your setup? Let me know in the comments below!&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Before You Go
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Please share&lt;/strong&gt; 📢 this with anyone that you think will be interested. It might help them, and it really helps me!&lt;/li&gt;
&lt;li&gt;Please &lt;strong&gt;give me loads of reactions / hearts&lt;/strong&gt;! 💖&lt;/li&gt;
&lt;li&gt;Please &lt;strong&gt;leave a comment&lt;/strong&gt; 💬. Interaction is good!&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Add a star&lt;/strong&gt; ⭐ on my repos!&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Follow&lt;/strong&gt; 👉 and &lt;strong&gt;subscribe&lt;/strong&gt; 🔔, so you don’t miss my content.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  References and Useful Links
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Standards, Hubs &amp;amp; Agent Platforms
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://agentskills.io/home" rel="noopener noreferrer"&gt;Agent Skills Specification &amp;amp; Open Standard&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://skills.sh/" rel="noopener noreferrer"&gt;Skills Hub &amp;amp; Directory (&lt;code&gt;skills.sh&lt;/code&gt;)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://antigravity.google/?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;Google Antigravity&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Related Dazbo Articles &amp;amp; Repositories
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dazbo.co.uk/" rel="noopener noreferrer"&gt;Dazbo's Portfolio&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/gde/dialling-our-agents-to-11-agent-skills-you-need-to-be-using-2o2k"&gt;&lt;em&gt;Dialling Our Agents to 11: Agent Skills You Need to be Using!&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/google-cloud/confused-about-where-to-put-your-agent-skills-ea778f3c64f3?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;&lt;em&gt;Confused About Where to Put Your Agent Skills?&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/google-cloud/automated-github-code-reviewsusing-google-gemini-7b4d027b3092?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;&lt;em&gt;Automated GitHub Code Reviews Using Google Gemini&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/derailed-dash/dazbo-agent-skills" rel="noopener noreferrer"&gt;Dazbo Agent Skills Repository (&lt;code&gt;derailed-dash/dazbo-agent-skills&lt;/code&gt;)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Key Agent Skills Repositories
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/google/skills" rel="noopener noreferrer"&gt;Google Skills (&lt;code&gt;google/skills&lt;/code&gt;)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/google/agents-cli" rel="noopener noreferrer"&gt;Google Agents CLI &amp;amp; Workflow Skills (&lt;code&gt;google/agents-cli&lt;/code&gt;)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/google-gemini/gemini-skills" rel="noopener noreferrer"&gt;Google Gemini API Skills (&lt;code&gt;google-gemini/gemini-skills&lt;/code&gt;)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/addyosmani/agent-skills" rel="noopener noreferrer"&gt;Addy Osmani Agent Skills (&lt;code&gt;addyosmani/agent-skills&lt;/code&gt;)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/agent_skills" rel="noopener noreferrer"&gt;Awesome LLM Apps Skills (&lt;code&gt;shubhamsaboo/awesome-llm-apps&lt;/code&gt;)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/coreyhaines31/marketingskills" rel="noopener noreferrer"&gt;Corey Haines Marketing Skills (&lt;code&gt;coreyhaines31/marketingskills&lt;/code&gt;)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/remotion-dev/skills" rel="noopener noreferrer"&gt;Remotion Video Skills (&lt;code&gt;remotion-dev/skills&lt;/code&gt;)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/vercel-labs/skills" rel="noopener noreferrer"&gt;Vercel Labs Skills (&lt;code&gt;vercel-labs/skills&lt;/code&gt;)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Academic Research &amp;amp; Benchmarks
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Paper: &lt;a href="https://arxiv.org/pdf/2605.24660" rel="noopener noreferrer"&gt;&lt;em&gt;“How Many Tools Should an LLM Agent See? A Chance-Corrected Answer”&lt;/em&gt;&lt;/a&gt; (Repantis et al., May 2026)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://gorilla.cs.berkeley.edu/leaderboard.html" rel="noopener noreferrer"&gt;Berkeley Function Calling Leaderboard (BFCL)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>agentskills</category>
      <category>progressivedisclosure</category>
      <category>googleantigravity</category>
      <category>agenticai</category>
    </item>
    <item>
      <title>Finally — Hard Caps to Limit Your Google Cloud Spend</title>
      <dc:creator>Darren "Dazbo" Lester</dc:creator>
      <pubDate>Wed, 29 Jul 2026 09:49:50 +0000</pubDate>
      <link>https://dev.to/gde/finally-hard-caps-to-limit-your-google-cloud-spend-1363</link>
      <guid>https://dev.to/gde/finally-hard-caps-to-limit-your-google-cloud-spend-1363</guid>
      <description>&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;For years, Google Cloud budget alerts were purely informational. They sent an email while your project quietly burned through your savings.&lt;/p&gt;

&lt;p&gt;I built my own Pub/Sub Killswitch to sleep peacefully at night, but it requires a bit of plumbing to install. What we really wanted was an easy option in the Google Cloud Console.&lt;/p&gt;

&lt;p&gt;Good news! Google has finally introduced native Cloud Spend Caps (currently in Public Preview). You can now hard-cap spend per service so an unexpected API leak or runaway script hits a 403 Permission Denied wall instead of creating a $10,000 bill.&lt;/p&gt;

&lt;p&gt;Here is how it works, how fast it triggers, and what you need to know…&lt;/p&gt;

&lt;h2&gt;
  
  
  What’s the Problem?
&lt;/h2&gt;

&lt;p&gt;Over the last couple of years I’ve read weekly horror stories about individuals getting hit for thousands, or even tens of thousands of dollars of unexpected costs from Google Cloud.&lt;/p&gt;

&lt;p&gt;Do a quick Google search, and you’ll find examples like…&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.tomshardware.com/tech-industry/artificial-intelligence/google-cloud-customer-wakes-up-to-usd18-000-bill-despite-usd7-budget-thanks-to-forgotten-public-api-key-attacker-put-in-60-000-requests-and-blasted-through-usd1-400-spending-cap" rel="noopener noreferrer"&gt;“Google Cloud customer wakes up to $18,000+ bill despite $7 budget, thanks to forgotten API key in published project — attacker put in 60,000+ requests and blasted through $1,400 spending cap”&lt;/a&gt; — Tom’s Hardware, April 2026&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.reddit.com/r/googlecloud/comments/1pimbs9/got_hit_with_a_65000_bill_overnight_from_gcs_due/" rel="noopener noreferrer"&gt;Got hit with a $65,000 bill overnight from GCS due to a spike in list object calls&lt;/a&gt; — Reddit, December 2025&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.reddit.com/r/googlecloud/comments/1tr4vp8/google_cloud_billed_me_19000_usd_r105000_brl/" rel="noopener noreferrer"&gt;Google Cloud billed me ~$19,000 USD (~R$105,000 BRL) after an API key breach — and the charges keep growing even after I deleted everything&lt;/a&gt; — Reddit, May 2026&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The big problem that most folks don’t understand is this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;GOOGLE BUDGET ALERTS WERE NOT HARD LIMITS. THEY DID NOT PREVENT YOU FROM SPENDING MORE THAN YOUR BUDGET.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Most of the examples I see follow the same pattern…&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A user follows Google best practice and sets a budget alert on their project. Say, $50 dollars per month.&lt;/li&gt;
&lt;li&gt;They go to bed.&lt;/li&gt;
&lt;li&gt;They wake up owing thousands.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Reading these stories was causing me so much distress. Both for the many people getting caught out, but also because the same thing happening to me felt like an inevitable ticking time bomb.&lt;/p&gt;

&lt;p&gt;In theory, I know more about Google Cloud than the average punter. I’m supposed to be a &lt;a href="https://developers.google.com/community/experts?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;Google Developer Expert (GDE)&lt;/a&gt; and &lt;a href="https://partners.cloud.google.com/google-cloud-ambassadors?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;Google Ambassador&lt;/a&gt;, after all!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;But still I was terrified!&lt;/em&gt; And I know at least a couple of fellow GDEs that have been hit with this. Which just goes to show: &lt;strong&gt;even if you know a lot about Google Cloud and think you’re doing everything right, it’s still possible to get caught out.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;And since Google didn’t offer any hard limit (aka &lt;em&gt;hard cap&lt;/em&gt;) mechanism, there was literally no off-the-shelf solution.&lt;/p&gt;

&lt;h2&gt;
  
  
  So I Built My Own Killswitch
&lt;/h2&gt;

&lt;p&gt;I built a mechanism that responds to budget alerts by detaching billing from whatever project(s) is/are associated with that alert. Sure, you can still get billing alert delays, but this mechanism typically stops any offending project inside of an hour of costs exceeding your budget. And this could be the difference that turns a £10,000 unexpected bill into a $100 unexpected bill. My solution is free and easy to install. And I blogged about it &lt;a href="https://medium.com/google-cloud/how-to-avoid-a-massive-cloud-bill-41a76251caba" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Using it requires a bit of setup…&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;You need to create your budget alerts, of course.&lt;/li&gt;
&lt;li&gt;You need those alerts to be sent to a Pub/Sub topic that you create.&lt;/li&gt;
&lt;li&gt;You need to deploy a Cloud Run Function that does the actual work of responding to the alert and disconnecting a project.&lt;/li&gt;
&lt;li&gt;You need to wire-up that Cloud Run Function such that it is triggered by events on the Pub/Sub topic.&lt;/li&gt;
&lt;li&gt;You need pay careful attention to the roles you assign to the service account that runs this Cloud Run project — particularly if you happen to have many different Google Cloud projects.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fq3e68ntbezwtoxvyw6nu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fq3e68ntbezwtoxvyw6nu.png" alt="My GCP Billing Killswitch" width="800" height="553"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Even though the solution is well-documented and all of the above is scripted, it’s still a fair bit of work. It can be daunting for many.&lt;/p&gt;

&lt;p&gt;I spoke to Google about this. A lot.&lt;/p&gt;

&lt;h2&gt;
  
  
  Google Introduced Cloud Spend Caps!
&lt;/h2&gt;

&lt;p&gt;They delivered!&lt;/p&gt;

&lt;p&gt;I tested this out in Private Preview over the last couple of weeks, but it went public today! So now y’all can use it too.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting Up a Spend Cap
&lt;/h2&gt;

&lt;p&gt;First, &lt;strong&gt;create a Budget&lt;/strong&gt; in the Google Cloud Console. Same place as before…&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fuhehlv5vjoq7idl8ohnd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fuhehlv5vjoq7idl8ohnd.png" alt="Create budget alert" width="800" height="626"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Traditionally, you would then set the amounts and then you’d see these available actions…&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgtut2ln8jcb2f5uji980.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgtut2ln8jcb2f5uji980.png" alt="Traditional budget alert — no spend cap" width="615" height="710"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But NOW you have the option to select &lt;strong&gt;“Spend cap enforcement”&lt;/strong&gt; when you create the budget.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkd9nrey8lc0c2duvhlzw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkd9nrey8lc0c2duvhlzw.png" alt="Spend cap enforcement" width="572" height="438"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you select this, &lt;strong&gt;you MUST then specify a service&lt;/strong&gt;. &lt;em&gt;(Currently you can only select one.)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5kv2t0csfgkgy7eo6gyv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5kv2t0csfgkgy7eo6gyv.png" alt="Specify a service" width="569" height="690"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Note that if you use the “Spend cap” type, you can no longer select the option to publish to Pub/Sub:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fp8bnisyt36lfuly8vu50.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fp8bnisyt36lfuly8vu50.png" alt="No Pub/Sub with Spend Caps" width="567" height="711"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once created, the new budget alert looks like this. Note how this new alert says &lt;em&gt;“Spend cap status: Configured”&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fu358sphvmfjhqavgazj4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fu358sphvmfjhqavgazj4.png" alt="Spend cap configured" width="799" height="263"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Trying It Out
&lt;/h2&gt;

&lt;p&gt;I started running up some cost on my Gemini API inside this project.&lt;/p&gt;

&lt;p&gt;Ooh, look! Inside my CI/CD pipeline I can see it’s hit a &lt;strong&gt;“403 — permission denied”&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F71xqdjdyhfl5rri8ykaf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F71xqdjdyhfl5rri8ykaf.png" alt="No permission!" width="800" height="510"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And I got this email, almost immediately.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7y2kuvckfm0i0vj6t38h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7y2kuvckfm0i0vj6t38h.png" alt="Spend cap reached" width="800" height="971"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It’s not too subtle! You’re gonna struggle to miss this in your inbox!!&lt;/p&gt;

&lt;p&gt;We can take a look in Cloud Console to see more information:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmsw6m4lxau6ay3p536rq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmsw6m4lxau6ay3p536rq.png" alt="Spend limit reached" width="799" height="355"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Okay, successful test! It worked exactly as we wanted it to.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Lift the Cap?
&lt;/h2&gt;

&lt;p&gt;What if we want to continue working with our service? In that case, we just need to lift the spend cap.&lt;/p&gt;

&lt;p&gt;Open your budget and then click on &lt;strong&gt;“Lift spend cap”&lt;/strong&gt; in the Console:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqta76f6t0zpdtxkq5emc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqta76f6t0zpdtxkq5emc.png" alt="Lift spend cap" width="800" height="539"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You’ll see this message:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fun6no0670ukt9pfypt87.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fun6no0670ukt9pfypt87.png" alt="Proceed?" width="799" height="466"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now you need to specify a new, &lt;em&gt;higher&lt;/em&gt; amount:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ft7plj54324je3wk0z1mk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ft7plj54324je3wk0z1mk.png" alt="Lift in progress" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You get a warning that it might take an hour to lift the cap. But for me, it took about 2 minutes:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ff0p1qx6o7yatehnta5mi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ff0p1qx6o7yatehnta5mi.png" alt="May take one hour" width="800" height="391"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then I received these two emails, nearly immediately:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fx1uh27yh113noc36eazt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fx1uh27yh113noc36eazt.png" alt="Email: spend cap lifted" width="800" height="785"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Spend cap updated:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdbrgxvzyy983q2fmh767.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdbrgxvzyy983q2fmh767.png" alt="Email: spend cap updated" width="800" height="859"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So when you’re working with spend caps, you always know exactly what’s going on.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Does This Differ From Spend Caps in AI Studio?
&lt;/h2&gt;

&lt;p&gt;It works the same way. But AI Studio only lets you set spend caps associated with Gemini API keys.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Most Frequently Asked Question…
&lt;/h2&gt;

&lt;p&gt;One of the biggest historical problems with budget alerts, and anything that leverages them (like my Billing Killswitch) is that the alerts are only triggered after billing cycle reconciliation. This results in a delay between your actual spend, and billing alerts firing. This delay could be hours. A lot of damage can be done to your credit card in a few hours!&lt;/p&gt;

&lt;p&gt;With the new spend capping feature, Google promises that “near real-time enforcement”, with the &lt;strong&gt;caps triggering within minutes of actual spend thresholds being met&lt;/strong&gt;. In my testing, it triggered within a couple of minutes.&lt;/p&gt;

&lt;p&gt;Two minutes rather than two hours? I’ll take it!&lt;/p&gt;

&lt;p&gt;Maybe, in the near future, we might expect some closer integration with the new Anomaly Detection feature. Wouldn’t it be nice if we had a toggle to enable capping to trigger based on the &lt;em&gt;prediction&lt;/em&gt; of a spend cap being hit in the next few minutes or hours? (For the SREs out there… This would be a similar approach to setting alerts based on the rate of error budget consumption.)&lt;/p&gt;

&lt;p&gt;Anyway, that’s my prediction. Let’s see!&lt;/p&gt;

&lt;h2&gt;
  
  
  Spend Cap Limitations?
&lt;/h2&gt;

&lt;p&gt;Just a couple that I noticed.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;At the moment, you have to set these caps one service at a time. It would be better if we could pick multiple services. So for now, I’ll still be using my Killswitch mechanism when I want to limit billing across the whole project or collections of projects.&lt;/li&gt;
&lt;li&gt;At the moment, you can’t have a cap and ALSO send a message to Pub/Sub. That might be useful for some.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;Native Cloud Spend Caps are an absolute game-changer. They provide the one thing cloud engineers have been begging for: actual, deterministic spend boundaries. If you’re building with high-throughput APIs like Gemini, get this configured immediately.&lt;/p&gt;

&lt;p&gt;Good architecture isn’t just about high availability — it’s about keeping your wallet intact!&lt;/p&gt;

&lt;h2&gt;
  
  
  Before You Go
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Please share&lt;/strong&gt; this with anyone that you think will be interested. It might help them, and it really helps me!&lt;/li&gt;
&lt;li&gt;Please &lt;strong&gt;give me loads of claps&lt;/strong&gt;! (Just hold down the clap button.)&lt;/li&gt;
&lt;li&gt;Please &lt;strong&gt;leave a comment&lt;/strong&gt; 💬. Interaction is good!&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Add a star&lt;/strong&gt; on the repo!&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Follow&lt;/strong&gt; and &lt;strong&gt;subscribe&lt;/strong&gt;, so you don’t miss my content.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Useful Links and References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://cloud.google.com/blog/topics/cost-management/new-early-anomalies-and-spend-caps-on-google-cloud-budgets?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;Google Cloud blog — Detect early and enforce firmly with Google Cloud’s enhanced cost controls for AI spend&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.google-cloud/how-to-avoid-a-massive-cloud-bill-41a76251caba" rel="noopener noreferrer"&gt;My GCP Billing Killswitch Blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/derailed-dash/gcp-billing-killswitch" rel="noopener noreferrer"&gt;My GCP Billing Killswitch on GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dazbo.co.uk/" rel="noopener noreferrer"&gt;Dazbo’s Portfolio&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>gcpbilling</category>
      <category>finops</category>
      <category>killswitch</category>
      <category>hardcap</category>
    </item>
    <item>
      <title>Building a Multi-Agent FinOps Solution with Google ADK, Levering Tools, MCP and Google-Managed Assistants</title>
      <dc:creator>Darren "Dazbo" Lester</dc:creator>
      <pubDate>Sun, 26 Jul 2026 06:10:51 +0000</pubDate>
      <link>https://dev.to/gde/building-a-multi-agent-finops-solution-with-google-adk-levering-tools-mcp-and-google-managed-lf</link>
      <guid>https://dev.to/gde/building-a-multi-agent-finops-solution-with-google-adk-levering-tools-mcp-and-google-managed-lf</guid>
      <description>&lt;h2&gt;
  
  
  Welcome Back!
&lt;/h2&gt;

&lt;p&gt;We’re continuing our &lt;em&gt;FinSavant&lt;/em&gt; series. In the previous two parts we:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Looked at the overall goals and architecture&lt;/li&gt;
&lt;li&gt;Setup our development environment, fully loaded with MCP servers and agent skills&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In this part we’re going to take a close look at the agent code. We’ll be looking at:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The various agents that make up the solution, and their tools.&lt;/li&gt;
&lt;li&gt;Different multi-agent orchestration patterns, and the pattern we selected for &lt;em&gt;FinSavant&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;How we handle cross-cutting concerns across agents.&lt;/li&gt;
&lt;li&gt;Testing with &lt;code&gt;ADK Web&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Optimisation&lt;/li&gt;
&lt;li&gt;Building and Testing a FastAPI &lt;em&gt;Backend-for-Frontend&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I’ll explain concepts and provide code snippets as we go. But don’t forget: you can always refer to the full code in the &lt;a href="https://github.com/derailed-dash/smart-gcp-finops" rel="noopener noreferrer"&gt;repo&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Let’s get cracking!&lt;/p&gt;

&lt;h2&gt;
  
  
  Series Orientation
&lt;/h2&gt;

&lt;p&gt;First, a quick reminder of where we are in the series:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://medium.com/google-cloud/finsavant-part-1-building-an-agentic-finops-platform-with-google-adk-a2ui-and-gemini-enterprise-248f59cea3a0?postPublishedType=repub" rel="noopener noreferrer"&gt;Goals, Architecture, and Tech Stack: Capabilities, project goals, target architecture, technology stack, and design decisions.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/google-cloud/finsavant-part-2-building-an-agentic-finops-platform-development-environment-setup-google-dd12b8b84ba0" rel="noopener noreferrer"&gt;Dev Environment Setup with Google Antigravity, ADK, Agents CLI, MCP &amp;amp; Skills&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Building the ADK Agent and API 📍 You are here.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Designing and Building the UI with Google Stitch and A2UI&lt;/li&gt;
&lt;li&gt;Deployment with Gemini Enterprise Agent Platform, Agent Runtime, Cloud Run and IAP&lt;/li&gt;
&lt;li&gt;Automating Deployment with CI/CD and Terraform&lt;/li&gt;
&lt;li&gt;Agent Observability, Evaluation, and Tuning with Gemini Enterprise Agent Platform&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Deciding on Our Agents
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;FinSavant&lt;/em&gt; is a FinOps solution that needs to do many different tasks. We could have one giant agent with a huge monolithic prompt. But this is an antipattern because:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The prompt becomes unwieldy.&lt;/li&gt;
&lt;li&gt;It’s too complicated to manage the possible journeys and workflows the prompt needs to manage.&lt;/li&gt;
&lt;li&gt;The agent is more likely to not follow the rules.&lt;/li&gt;
&lt;li&gt;We have to give our giant agent access to all the tools, meaning it’s less likely to pick the right one for a task.&lt;/li&gt;
&lt;li&gt;The agent is ultimately less reliable and less consistent.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2mvh37phy9owa82pyy2f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2mvh37phy9owa82pyy2f.png" alt="The Monolithic Agent Antipattern — What happens when you give a single agent every tool in the repository." width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A much better approach is to have individual agents that each have a clear purpose, and which each have a limited set of tools they can use. We can then have a root agent that orchestrates the agents and decides which agent to use for each task.&lt;/p&gt;

&lt;p&gt;Something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fi5jqxmv71sbqtxdym6p2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fi5jqxmv71sbqtxdym6p2.png" alt="Multi-agent design" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So this is what we’re going to build!&lt;/p&gt;

&lt;h2&gt;
  
  
  Agent Directory Structure
&lt;/h2&gt;

&lt;p&gt;Let’s deep-dive on the &lt;code&gt;/agent&lt;/code&gt; directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;smart-gcp-finops/
├── agent/                     # Core ADK Agent &amp;amp; Agent Runtime package
│   ├── finops_agent/
│   │   ├── agents/                  # Subagent definitions
│   │   │   ├── billing_explorer_agent.py       # BigQuery spend trends &amp;amp; cost breakdown subagent
│   │   │   ├── cloud_advisor_agent.py          # Cloud Assist &amp;amp; operational diagnosis subagent
│   │   │   ├── infrastructure_auditor_agent.py # Idle/zombie resource waste audit subagent
│   │   │   ├── knowledge_assistant_agent.py    # Developer Knowledge &amp;amp; best practice grounding subagent
│   │   │   └── root_cause_analyst_agent.py     # Spend anomaly, Audit Logs, and CAI correlation subagent
│   │   ├── app_utils/               # Shared tools and utilities
│   │   │   ├── a2a.py                    # Agent-to-Agent (A2A) protocol endpoints
│   │   │   ├── cai_tools.py              # Cloud Asset Inventory ADK tool wrappers
│   │   │   ├── cai_utils.py              # Cloud Asset Inventory API search &amp;amp; history helpers
│   │   │   ├── context.py                # Session context state helpers
│   │   │   ├── credentials.py            # ADC and Service Account auth helpers
│   │   │   ├── dashboard_data.py         # Pre-computed spend analysis &amp;amp; UI dataset generator
│   │   │   ├── logging_and_telemetry.py  # Cloud Logging &amp;amp; Audit Logs intra-day telemetry
│   │   │   ├── mcp_config.py             # Remote MCP toolsets &amp;amp; OAuth2 auth providers
│   │   │   ├── project_discovery.py      # Dynamic Google project hierarchy discovery
│   │   │   ├── services.py               # ADK services
│   │   │   ├── tools.py                  # BigQuery spend analysis &amp;amp; SQL execution tools
│   │   │   ├── typing.py                 # Pydantic schemas &amp;amp; structured output models
│   │   │   ├── zombie_resources.py       # Idle &amp;amp; zombie GCP resource detection logic
│   │   │   └── zombie_tools.py           # Tools for zombie waste auditing
│   │   ├── agent.py                 # Root agent
│   │   ├── callbacks.py             # Global callbacks
│   │   ├── client.py                # Gemini &amp;amp; MCP client initialisation
│   │   └── config.py                # Agent config
│   └── pyproject.toml         # Agent package dependencies
├── bff/                       # Backend-for-Frontend FastAPI service
├── docs/                      # Documentation
├── frontend/                  # React UI
├── scripts/                   # Helper &amp;amp; environment scripts
├── tests/                     # Unit &amp;amp; integration test suites
├── Dockerfile                 # Unified dev container build
├── Makefile                   # Development &amp;amp; deployment convenience
└── pyproject.toml             # Root workspace dependencies
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You might be wondering about the directory naming here — why do we have &lt;code&gt;agent/&lt;/code&gt;, then &lt;code&gt;finops_agent/&lt;/code&gt;, and then &lt;code&gt;agents/&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;It might look a bit repetitive at first glance, but there’s clear logic behind it:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;agent/&lt;/code&gt;&lt;/strong&gt;:&lt;br&gt;&lt;br&gt;
This is our top-level monorepo component folder, sitting alongside &lt;code&gt;/bff&lt;/code&gt;, &lt;code&gt;/frontend&lt;/code&gt;, and &lt;code&gt;/deployment&lt;/code&gt;. It houses all build manifests (&lt;code&gt;pyproject.toml&lt;/code&gt;, &lt;code&gt;Dockerfile&lt;/code&gt;) and dependencies specific to the agent backend. This will be important later when we deploy to the Agent Runtime.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;finops_agent/&lt;/code&gt;&lt;/strong&gt;:&lt;br&gt;&lt;br&gt;
This is the actual Python package directory. By using a distinct package name rather than &lt;code&gt;agent&lt;/code&gt;, we avoid Python module name collisions and allow clean, explicit imports (e.g. &lt;code&gt;from finops_agent.agent import root_agent&lt;/code&gt;). This is also the standard layout expected by ADK's &lt;code&gt;agents-cli&lt;/code&gt; tooling.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;agents/&lt;/code&gt;&lt;/strong&gt;:&lt;br&gt;&lt;br&gt;
This nested directory houses our individual subagent definitions (&lt;code&gt;billing_explorer_agent.py&lt;/code&gt;, &lt;code&gt;cloud_advisor_agent.py&lt;/code&gt;, etc.). Separating them into their own module keeps the subagents isolated from the root coordinator (&lt;code&gt;agent.py&lt;/code&gt;), global callbacks (&lt;code&gt;callbacks.py&lt;/code&gt;), and utilities (&lt;code&gt;app_utils/&lt;/code&gt;).&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The Specialised Agents &amp;amp; Their Tools
&lt;/h2&gt;

&lt;p&gt;With our directory structure in place, let’s look at each of our agents in detail:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. &lt;code&gt;FinOpsCoordinator&lt;/code&gt; (Root Agent)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Purpose&lt;/strong&gt;: Serves as the front door and central router for all user queries.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Model&lt;/strong&gt;: &lt;code&gt;gemini-3.5-flash-lite&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tools&lt;/strong&gt;: Uses &lt;strong&gt;zero direct tools&lt;/strong&gt;, e.g. no SQL or Cloud Asset Inventory access. Its sole capability is delegating to specialised subagents using ADK’s native agent routing mechanisms.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Selective Routing Rules&lt;/strong&gt;: Prompt instructions strictly enforce selective delegation. For example, if the user asks solely about costs, it delegates exclusively to &lt;code&gt;BillingExplorer&lt;/code&gt;, avoiding wasteful multi-agent sweeps.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here’s a snippet of the code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;AGENT_INSTRUCTION&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;You are the FinOpsCoordinator root agent.
Your primary role is to receive user requests, understand their intent, 
and delegate cost analysis, auditing, optimization, and Q&amp;amp;A tasks to the appropriate 
specialist subagents:

1. BillingExplorer: Use for spend aggregates, SKU prices, cost trends, forecasting, 
   and Cost Explorer (explorer/dashboard) dashboards.
2. InfrastructureAuditor: Use for auditing zombie resources like idle static IPs 
   or unattached disks (recommendations dashboard).
3. CloudAdvisor: Use for active GCP rightsizing and resource-level cost/performance 
   optimisations.
4. KnowledgeAssistant: Use for general GCP Q&amp;amp;A and grounding recommendations in 
   official architectural guidelines.
5. RootCauseAnalyst: Use for analyzing cost spikes by correlating BigQuery 
   spend shifts with CAI configuration change history.

CRITICAL SELECTIVE ROUTING AND A2UI PRESERVATION RULES:
1. You MUST only delegate tasks to the specific subagent(s) directly relevant 
   to the user&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;s request.
   - If the user only asks about costs, spend trends, SKU prices, or budgets, 
     ONLY invoke BillingExplorer.
     Do NOT invoke CloudAdvisor or InfrastructureAuditor.
   - If the user asks for active recommendations, rightsizing, or optimizations, 
     identify the top active cost-driver services and projects already discovered 
     in conversation history (e.g. Vertex AI, Gemini API, BigQuery), 
     and pass those specific services/projects when delegating to CloudAdvisor.
   - If the user asks to &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Audit Best Practices&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt; or assess services against 
     GCP architectural guidelines, identify the top cost-driving services from 
     conversation history (e.g. Vertex AI, Gemini API, BigQuery) and ONLY 
     invoke KnowledgeAssistant to retrieve official GCP architectural best practices 
     and citations for those specific services.
   - If the user only asks about zombie resources, idle IPs, or unattached disks, 
     ONLY invoke InfrastructureAuditor.
2. Do NOT run a full multi-agent audit (calling multiple subagents) unless the user 
   explicitly requests a &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;full audit&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;, &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;comprehensive review&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;, &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;complete environment analysis,
   or asks a multi-faceted question that spans multiple domains.
   Keep simple queries fast and single-scoped!
3. CRITICAL A2UI PAYLOAD PRESERVATION:
   When a subagent (such as BillingExplorer or InfrastructureAuditor) returns a response 
   containing structured ```

json+a2ui ...

 ``` code blocks, you MUST preserve and 
   re-emit those exact ```

json+a2ui ...

 ``` code blocks unchanged in your final output 
   so the React frontend can render dynamic A2UI dashboard components!

RESPONSE SYNTHESIS &amp;amp; HELPFULNESS GUIDELINES:
1. Executive Summary First: Always lead with a crisp 1-2 sentence summary directly 
   answering the user&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;s prompt (e.g. total spend, primary cost driver, top recommendation).
2. Scannable &amp;amp; Structured Formatting: Use clear Markdown headings, bold key financial metrics
   (e.g. **£41.34 GBP**), and scannable bullet points.
3. Proactive &amp;amp; Actionable Next Steps: Conclude with a helpful, context-aware follow-up 
   suggestion (e.g. offering to analyze cost spikes on a specific project, query rightsizing options).
4. Tone: Senior FinOps advisory tone — professional, precise, and encouraging without unnecessary boilerplate.
&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

&lt;span class="n"&gt;root_agent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Agent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;root_agent&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nc"&gt;ConfiguredGemini&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fast_model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;retry_options&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;types&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;HttpRetryOptions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;attempts&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;use_interactions_api&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;instruction&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;AGENT_INSTRUCTION&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;
    &lt;span class="n"&gt;sub_agents&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="n"&gt;billing_explorer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;infrastructure_auditor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;cloud_advisor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;knowledge_assistant&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;root_cause_analyst&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;before_agent_callback&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="n"&gt;before_agent_clean_history&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;before_agent_reset_tool_call_counter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;before_agent_discover_projects&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;before_agent_cache_lookup&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;before_tool_callback&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;before_tool_check_limit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;before_model_callback&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;before_model_bypass&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;after_agent_callback&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;after_agent_save_cache&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;App&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;root_agent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;root_agent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;finops_agent&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;context_cache_config&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nc"&gt;ContextCacheConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;min_tokens&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2048&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;# Trigger caching for large prompts/histories on Vertex AI / Gemini
&lt;/span&gt;        &lt;span class="n"&gt;ttl_seconds&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;600&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;# Store the cache for up to 10 minutes
&lt;/span&gt;        &lt;span class="n"&gt;cache_intervals&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;# Refresh after 10 turns
&lt;/span&gt;    &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;plugins&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;DefensiveToolErrorPlugin&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nc"&gt;FinOpsTelemetryPlugin&lt;/span&gt;&lt;span class="p"&gt;()],&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There’s a few interesting things to note about this agent:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We set the &lt;strong&gt;model&lt;/strong&gt; to &lt;code&gt;settings.fast_model&lt;/code&gt;. This is configured by an environment variable and here we've set it to &lt;a href="https://docs.cloud.google.com/gemini-enterprise-agent-platform/models/gemini/3-5-flash-lite?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;&lt;code&gt;gemini-3.5-flash-lite&lt;/code&gt;&lt;/a&gt;. We use this here for fast, low-cost responses and routing. We don't need heavy reasoning in the orchestrator agent.&lt;/li&gt;
&lt;li&gt;We tell the root agent about all the &lt;strong&gt;subagents&lt;/strong&gt; it can delegate to in the &lt;code&gt;sub_agents&lt;/code&gt; parameter.&lt;/li&gt;
&lt;li&gt;It has &lt;strong&gt;no tools&lt;/strong&gt;!&lt;/li&gt;
&lt;li&gt;Native Gemini &lt;a href="https://docs.cloud.google.com/gemini-enterprise-agent-platform/models/context-cache/context-cache-overview?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;&lt;strong&gt;context caching&lt;/strong&gt;&lt;/a&gt; is enabled. This caches pre-processed system instructions, subagent definitions, and conversation history. &lt;em&gt;Why is this useful?&lt;/em&gt; In a multi-turn chat session, without caching, the LLM has to re-parse and re-tokenise the exact same large system instructions and tool/subagent declarations on every single turn. Context caching slashes input token costs by up to 75–90% and significantly reduces time-to-first-token (TTFT) turn latency. Booyah!&lt;/li&gt;
&lt;li&gt;There are &lt;a href="https://adk.dev/callbacks/" rel="noopener noreferrer"&gt;&lt;strong&gt;agent callbacks&lt;/strong&gt;&lt;/a&gt; (defined on &lt;code&gt;root_agent&lt;/code&gt;) and &lt;a href="https://adk.dev/plugins/" rel="noopener noreferrer"&gt;&lt;strong&gt;global application plugins&lt;/strong&gt;&lt;/a&gt; (defined on &lt;code&gt;App&lt;/code&gt;) for managing lifecycle hooks across the execution loop.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Quick Aside: ADK Callbacks vs App Plugins
&lt;/h3&gt;

&lt;p&gt;In ADK, lifecycle hooks allow deterministic Python functions to execute at specific points in the execution pipeline, i.e. before/after an agent runs, before/after a model call, or before/after a tool executes.&lt;/p&gt;

&lt;p&gt;However, there is an important distinction between &lt;strong&gt;Agent-level Callbacks&lt;/strong&gt; and &lt;strong&gt;App-level Plugins&lt;/strong&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Agent-Level Callbacks&lt;/strong&gt;:&lt;br&gt;&lt;br&gt;
Attached to a specific agent (like &lt;code&gt;root_agent&lt;/code&gt;). These fire &lt;strong&gt;once&lt;/strong&gt; when that specific agent initiates its execution. For instance, &lt;code&gt;before_agent_discover_projects&lt;/code&gt; runs on the &lt;code&gt;root_agent&lt;/code&gt; at the very start of a user turn. It calls the Cloud Billing API (&lt;code&gt;billingAccounts.projects.list&lt;/code&gt;) to retrieve all linked GCP project IDs and populates &lt;code&gt;session.state['allowed_projects']&lt;/code&gt;. Because this happens before delegating, every subagent can simply read &lt;code&gt;allowed_projects&lt;/code&gt; from session state. We don't re-run the API call for subagents!&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;App-Level Plugins (&lt;code&gt;BasePlugin&lt;/code&gt;)&lt;/strong&gt;:&lt;br&gt;&lt;br&gt;
These are registered globally on the &lt;code&gt;App&lt;/code&gt; container via &lt;code&gt;App(plugins=[...])&lt;/code&gt;. They subclass &lt;code&gt;BasePlugin&lt;/code&gt; and hook into &lt;strong&gt;every&lt;/strong&gt; agent turn and tool call across the entire hierarchy (root coordinator and subagents alike).&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here are a few concrete examples of how we leverage callbacks and plugins in &lt;em&gt;FinSavant&lt;/em&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Error Handling (&lt;code&gt;DefensiveToolErrorPlugin&lt;/code&gt;)&lt;/strong&gt;: Globally intercepts unhandled tool exceptions across any subagent, storing formatted errors in session state so the coordinator can inform the user gracefully without crashing the process.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Logging and Telemetry (&lt;code&gt;FinOpsTelemetryPlugin&lt;/code&gt;)&lt;/strong&gt;: Automatically instruments OpenTelemetry spans; logs agent handoffs, model execution latency, and token consumption across all turns.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dynamic Project Discovery (&lt;code&gt;before_agent_discover_projects&lt;/code&gt;)&lt;/strong&gt;: Attached to &lt;code&gt;root_agent&lt;/code&gt;. Fires once at turn start to discover live GCP project IDs and write them to &lt;code&gt;session.state['allowed_projects']&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Subagent History Cleaning (&lt;code&gt;before_agent_clean_history&lt;/code&gt;)&lt;/strong&gt;: Attached to &lt;code&gt;root_agent&lt;/code&gt;. Fires before the root agent processes a subagent's return, converting subagent &lt;code&gt;finish_task&lt;/code&gt; responses into plain-text user context.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Turn-Level Response Caching (&lt;code&gt;before_agent_cache_lookup&lt;/code&gt; &amp;amp; &lt;code&gt;after_agent_save_cache&lt;/code&gt;)&lt;/strong&gt;: Attached to &lt;code&gt;root_agent&lt;/code&gt;. This checks the current issued prompt before execution. It uses the fast model to determine if this prompt is semantically very similar to a previous prompt in the conversation. If it is, we can return a response from the cached responses. Instead of duplicating logging or exception handlers inside every subagent constructor, ADK allows registering global plugins on the root &lt;code&gt;App&lt;/code&gt;:&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tool Call Limiting (&lt;code&gt;before_tool_check_limit&lt;/code&gt;)&lt;/strong&gt;: Attached to &lt;code&gt;root_agent&lt;/code&gt;. This callback enforces a tool ceiling per turn, ensuring that we don't end up with runaway subagent loops that try to make tool calls dozens of times.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;before_tool_check_limit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tool&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Any&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Any&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;tool_context&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Any&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Defensive callback to count and limit tool calls in a single turn to prevent runaways.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tool_context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;_turn_tool_call_count&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="n"&gt;tool_context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;_turn_tool_call_count&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt;
    &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Tool call #%d in this turn: executing %s with arguments: %s&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;tool&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;max_tool_calls_per_turn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Defensive stop triggered: Tool call count exceeded limit of %d!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;max_tool_calls_per_turn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;RuntimeError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Defensive stop: too many tool calls executed in a single turn.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Neat, right?&lt;/p&gt;

&lt;h3&gt;
  
  
  2. &lt;code&gt;BillingExplorer&lt;/code&gt; (Spend Aggregation &amp;amp; Dashboards)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Model&lt;/strong&gt;: &lt;code&gt;gemini-3.6-flash&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tools&lt;/strong&gt;: &lt;code&gt;get_precomputed_spend_analysis&lt;/code&gt;, &lt;code&gt;execute_cached_bigquery_sql&lt;/code&gt;, native &lt;code&gt;BigQueryToolset&lt;/code&gt;, &lt;code&gt;get_session_value&lt;/code&gt;, &lt;code&gt;set_session_value&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Responsibilities&lt;/strong&gt;: Aggregates Month-to-Date (MTD) spend, analyzes SKU costs, forecasts end-of-month spend, and constructs structured explorer and dashboard JSON+A2UI payloads for the React canvas. (More on that in a later part, naturally!)
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;finops_agent.app_utils.tools&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;BLACKBOARD_KEY_INSTRUCTIONS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;execute_cached_bigquery_sql&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;get_precomputed_spend_analysis&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;get_session_value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;set_session_value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;finops_agent.app_utils.typing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;TaskOutput&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;finops_agent.client&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;ConfiguredGemini&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;bigquery_toolset&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;finops_agent.config&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;settings&lt;/span&gt;

&lt;span class="n"&gt;BILLING_EXPLORER_INSTRUCTION&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;You are the BillingExplorer subagent.
Use the `get_precomputed_spend_analysis` tool to retrieve pre-computed cloud costs, period-over-period trends, cost drivers, cost forecasts, and Secret Manager/GCS zombie waste metrics. Pass the `days` parameter matching the timeframe requested by the user (e.g. `days=7` for 7 days, `days=14` for 14 days, `days=30` for 30 days, `days=60` for 60 days, `days=90` for 90 days; default to 30 if unspecified).

CRITICAL COST FORECASTING &amp;amp; TOOL SELECTION RULES:
1. For ALL spend queries, cost trend analysis, and cost forecasting (including prompts like &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Run Cost Forecast&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;, &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Future Trend&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;, &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Projected Spend&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;), ALWAYS call `get_precomputed_spend_analysis(days=...)`.
2. `get_precomputed_spend_analysis` ALREADY computes the Month-to-Date (MTD) spend, period-over-period trends, and the projected end-of-month spend forecast in Python instantaneously.
3. Do NOT attempt to run standard SQL queries or construct custom BigQuery ML statements (`CREATE OR REPLACE MODEL`, `ML.FORECAST`) directly if `get_precomputed_spend_analysis` is available.
4. NEVER execute multi-query loops or attempt dataset/model creation. Use the result returned by `get_precomputed_spend_analysis` to generate the complete report in a single tool call!

Based on the dictionary returned by `get_precomputed_spend_analysis`, generate a concise final report:
1. Total Spend and currency.
2. Top Cost Drivers by Service.
3. Period-over-Period Changes &amp;amp; Trends (percentage changes).
4. Major cost spikes (date and service/cost).
5. Zombie/inactive waste (secrets, buckets, etc).

&amp;lt; trimmed for readability &amp;gt;

CRITICAL: CONCISE SYNTHESIS RULE
Write your report in a highly concise style. Keep the markdown text under 250 words total.

CRITICAL COORDINATION AND TERMINATION RULES:
1. Call `finish_task` and pass the complete final markdown report directly into the `result` parameter.
2. Once you have generated the report and returned it via `finish_task`, stop execution.
&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

&lt;span class="n"&gt;billing_explorer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Agent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;billing_explorer&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Specialised subagent for querying Standard and Resource-level billing tables, summarizing Month-to-Date (MTD) cloud costs, forecasting future spend, identifying top cost drivers, and generating Cost Explorer (explorer/dashboard) workspaces.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nc"&gt;ConfiguredGemini&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;retry_options&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;types&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;HttpRetryOptions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;attempts&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;use_interactions_api&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;instruction&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;COMMON_AGENT_HEADER&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;BILLING_EXPLORER_INSTRUCTION&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="n"&gt;get_precomputed_spend_analysis&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;execute_cached_bigquery_sql&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;bigquery_toolset&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;get_session_value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;set_session_value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;mode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;task&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;output_schema&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;TaskOutput&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;disallow_transfer_to_peers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;disallow_transfer_to_parent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Some notes about this agent…&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Here we use &lt;a href="https://docs.cloud.google.com/gemini-enterprise-agent-platform/models/gemini/3-6-flash?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;&lt;code&gt;gemini-3.6-flash&lt;/code&gt;&lt;/a&gt; (in &lt;code&gt;settings.model&lt;/code&gt;) rather than the &lt;em&gt;fast(er)&lt;/em&gt; model. We need more reasoning power in this agent. So here we see another benefit of using separate subagents: we can use different models and parameters for each one.&lt;/li&gt;
&lt;li&gt;It has &lt;strong&gt;no subagents&lt;/strong&gt;, but it has several &lt;strong&gt;tools&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Some tools, like &lt;code&gt;bigquery_toolset&lt;/code&gt; are out-of-the-box in ADK. Others are custom tools that I've written myself.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;code&gt;bigquery_toolset&lt;/code&gt; allows the agent to interact with BigQuery (such as executing SQL queries) in response to natural language prompts. Let's take a look at how we configure this.&lt;/p&gt;

&lt;p&gt;You can see I passed &lt;code&gt;bigquery_toolset&lt;/code&gt; as a parameter to the tools list. We've defined this in &lt;code&gt;finops_agent/client.py&lt;/code&gt; which serves as my centralised hub for client initialisation. Instead of having the root orchestrator and individual subagents instantiate their own SDK clients or tools independently, &lt;code&gt;client.py&lt;/code&gt; sets up thread-safe, shared resources at the module level. Here I'll show you a few snippets from this file, for our BQ tools setup:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Imports
&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;google.auth&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;google.adk.integrations.bigquery&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;BigQueryCredentialsConfig&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;BigQueryToolset&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;finops_agent.config&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;settings&lt;/span&gt;
&lt;span class="c1"&gt;# Other imports...
# Setup ADC and then configure BQ tools to use it
&lt;/span&gt;&lt;span class="n"&gt;credentials&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;google&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;default&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;credentials_config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;BigQueryCredentialsConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;credentials&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;credentials&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;EXCLUDED_BQ_TOOL_KEYWORDS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;execute&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;query&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;forecast&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;anomalies&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;bq_tool_filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tool&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Any&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Any&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Excludes certain BigQuery tools from the exposed tool list to prevent bypass of custom tools.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tool&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="nf"&gt;any&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;keyword&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;keyword&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;EXCLUDED_BQ_TOOL_KEYWORDS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;bigquery_toolset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;BigQueryToolset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;credentials_config&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;credentials_config&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;tool_filter&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;bq_tool_filter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can see I’ve added a tool filtering guardrail, which limits which of the out-of-the-box tools are exposed to the agent. For example, I don’t want to expose the standard SQL execution tools to the agent, as I want to use my custom tools instead, such as &lt;code&gt;execute_cached_bigquery_sql&lt;/code&gt; and &lt;code&gt;get_precomputed_spend_analysis&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Not a lot of code required!&lt;/p&gt;

&lt;p&gt;Now, let’s take a look at one my custom tools: &lt;code&gt;get_precomputed_spend_analysis&lt;/code&gt;. This bespoke tool performs some specific SQL queries. I've provided the queries I want it to execute in the function, since this is more token-efficient (and reliable) than getting Gemini to craft a SQL query for me in real-time. It's also &lt;strong&gt;much faster&lt;/strong&gt;! (I'll talk a bit more about this later in this article.)&lt;/p&gt;

&lt;p&gt;The tool’s description looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_precomputed_spend_analysis&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;days&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tool_context&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ToolContext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Any&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Pre-computes Month-to-Date (MTD) cloud costs, period-over-period trends, cost drivers, daily cost spikes, and Secret Manager/GCS zombie waste in Python for the given duration.
    Reuses cached BQ queries.
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

    &lt;span class="c1"&gt;# Now I define the actual SQL queries and execute them
&lt;/span&gt;    &lt;span class="c1"&gt;# Skipping in the snippet for brevity
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It’s &lt;strong&gt;very important&lt;/strong&gt; that all of our custom tools have &lt;strong&gt;good descriptions&lt;/strong&gt; — as docstrings — like this. This helps our agent always pick the right tool for a given task.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. &lt;code&gt;InfrastructureAuditor&lt;/code&gt; (Waste &amp;amp; Zombie Resource Auditing)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Model&lt;/strong&gt;: &lt;code&gt;gemini-3.6-flash&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tools&lt;/strong&gt;: &lt;code&gt;list_zombie_resources&lt;/code&gt;, &lt;code&gt;get_precomputed_spend_analysis&lt;/code&gt;, &lt;code&gt;get_cai_metadata_for_resources&lt;/code&gt;, &lt;code&gt;get_cai_history_for_resource&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Responsibilities&lt;/strong&gt;: Scans for unattached Persistent Disks, idle static external IP addresses, inactive GCS storage buckets, and orphaned Secret Manager secrets. Generates recommendations JSON+A2UI payloads.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. &lt;code&gt;CloudAdvisor&lt;/code&gt; (Live Guidance Proxy)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Model&lt;/strong&gt;: &lt;code&gt;gemini-3.5-flash-lite&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tools&lt;/strong&gt;: &lt;code&gt;cloud_assist_mcp_toolset&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Responsibilities&lt;/strong&gt;: Proxies requests to Google Gemini Cloud Assist MCP for infrastructure recommendations.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is a pretty simple agent that makes use of &lt;a href="https://cloud.google.com/products/gemini/cloud-assist?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;Google Cloud Assist&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Let’s look at the relevant code…&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;finops_agent.app_utils.mcp_config&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;cloud_assist_mcp_toolset&lt;/span&gt;
&lt;span class="c1"&gt;# Other imports
&lt;/span&gt;
&lt;span class="n"&gt;CLOUD_ADVISOR_INSTRUCTION&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;You are the CloudAdvisor subagent.
Use Gemini Cloud Assist tools (ask_cloud_assist, investigate_issue) to retrieve active rightsizing recommendations, perform operational issue diagnostics, and optimize performance/cost for active GCP resources.

CRITICAL OPERATIONAL DIAGNOSIS &amp;amp; RIGHTSIZING RULES:
1. OPERATIONAL ANOMALIES: If the session context or prompt indicates active operational errors (e.g. `today_operational_anomaly == True` or crash loops), use `investigate_issue` or `ask_cloud_assist` to query active GCP Monitoring alerts, failing services, and system diagnostics for the affected project/service.
2. DISCOVERED CONTEXT: BEFORE querying, inspect the prompt and session context for the top active services and projects ALREADY DISCOVERED in this session.
3. Focus all recommendation and diagnostic queries (`ask_cloud_assist`, `investigate_issue`) SPECIFICALLY on those identified active services and projects.
4. Do NOT output generic boilerplate recommendations for unconfigured services (like GKE or Compute Engine VMs if they are not driving spend). Every recommendation MUST be tailored directly to the discovered active workloads.

CRITICAL AUTH &amp;amp; FALLBACK RULES:
1. If `ask_cloud_assist` returns recommendations or diagnostic findings, compile them into a clear, structured report detailing estimated monthly savings or operational remediation steps.
2. If `ask_cloud_assist` returns a 403 Forbidden or permission error for certain projects:
   - Highlight any recommendations retrieved from accessible active projects.
   - For projects lacking Recommender permissions, provide high-value, actionable optimization guidance strictly tailored to the specific active services discovered in the environment.
3. Always invoke `finish_task` with your complete, formatted Markdown report in the `result` argument.
&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

&lt;span class="n"&gt;cloud_advisor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Agent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cloud_advisor&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Specialised subagent that calls Gemini Cloud Assist tools to retrieve active rightsizing recommendations, perform operational issue diagnostics, and optimize performance/cost for active GCP resources.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nc"&gt;ConfiguredGemini&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fast_model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;retry_options&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;types&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;HttpRetryOptions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;attempts&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;use_interactions_api&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;instruction&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;COMMON_AGENT_HEADER&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;CLOUD_ADVISOR_INSTRUCTION&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="n"&gt;cloud_assist_mcp_toolset&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;get_session_value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;mode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;task&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;output_schema&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;TaskOutput&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;disallow_transfer_to_peers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;disallow_transfer_to_parent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we’ll look at how we define &lt;code&gt;cloud_assist_mcp_toolset&lt;/code&gt;. Obviously, we're using MCP and the actual configuration is defined in my &lt;code&gt;app_utils/mcp_config.py&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;GcpMcpAuthProvider&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Provides valid OAuth2 headers for Google Cloud remote MCP connections.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;scopes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_scopes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;scopes&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://www.googleapis.com/auth/cloud-platform&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_credentials&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_lock&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;threading&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Lock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__call__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ReadonlyContext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
        &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_lock&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_credentials&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_credentials&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;google&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;default&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;scopes&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_scopes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_credentials&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;valid&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_credentials&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;refresh&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

            &lt;span class="n"&gt;token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_credentials&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Authorization&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Bearer &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;x-goog-user-project&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;google_cloud_project&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Content-Type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;application/json&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Accept&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;application/json, text/event-stream&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Gemini Cloud Assist MCP Toolset Configuration
&lt;/span&gt;&lt;span class="n"&gt;cloud_assist_mcp_toolset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;McpToolset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;connection_params&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nc"&gt;StreamableHTTPConnectionParams&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://geminicloudassist.googleapis.com/mcp&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;header_provider&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nc"&gt;GcpMcpAuthProvider&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So now, whenever we need an &lt;em&gt;investigation&lt;/em&gt;, we can get Gemini Cloud Assist to do the heavy lifting. Nice!&lt;/p&gt;

&lt;h3&gt;
  
  
  5. &lt;code&gt;KnowledgeAssistant&lt;/code&gt; (GCP Architecture Grounding)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Model&lt;/strong&gt;: &lt;code&gt;gemini-3.5-flash-lite&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tools&lt;/strong&gt;: &lt;code&gt;dev_knowledge_mcp_toolset&lt;/code&gt; (Google Developer Knowledge MCP: &lt;code&gt;answer_query&lt;/code&gt;, &lt;code&gt;search_documents&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Responsibilities&lt;/strong&gt;: Grounds cost optimisation and architecture advice directly in official Google Cloud developer and architecture framework documentation, returning authoritative citations.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The code for this agent is very simple; it’s basically just the prompt and the use of the Google Developer Knowledge MCP toolset. The toolset itself is defined using the same pattern that we used previously for &lt;code&gt;cloud_assist_mcp_toolset&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;KNOWLEDGE_ASSISTANT_INSTRUCTION&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;You are the KnowledgeAssistant subagent.
Query the Developer Knowledge MCP to retrieve and ground cost optimization recommendations in official GCP architectural guidelines.

GUIDELINES:
1. Identify the specific GCP services provided in the user prompt or identified as top cost drivers (e.g. Vertex AI, Gemini API, BigQuery, Cloud Storage).
2. Query the Developer Knowledge MCP to find official Google Cloud cost optimization strategies, architectural patterns, quota management, lifecycle policies, and scaling guidelines for those specific services.
3. Always provide inline citations referencing official GCP documentation when presenting architectural advice or product recommendations.
4. When outputting references or citations, ALWAYS format them as standard single-line Markdown links: [Title](URL). Never insert line breaks or whitespace inside the URL or between `]` and `(`.
&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

&lt;span class="n"&gt;knowledge_assistant&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Agent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;knowledge_assistant&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Specialised subagent that queries the Developer Knowledge MCP to retrieve and ground cost optimization recommendations in official GCP architectural guidelines and best practices.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nc"&gt;ConfiguredGemini&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fast_model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;retry_options&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;types&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;HttpRetryOptions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;attempts&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;use_interactions_api&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;instruction&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;COMMON_AGENT_HEADER&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;KNOWLEDGE_ASSISTANT_INSTRUCTION&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="n"&gt;dev_knowledge_mcp_toolset&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;mode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;single_turn&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;disallow_transfer_to_peers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;disallow_transfer_to_parent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  6. &lt;code&gt;RootCauseAnalyst&lt;/code&gt; (Spike &amp;amp; Drift Correlation)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Model&lt;/strong&gt;: &lt;code&gt;gemini-3.6-flash&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tools&lt;/strong&gt;: &lt;code&gt;get_today_top_services_and_usage&lt;/code&gt;, &lt;code&gt;investigate_today_service_logs&lt;/code&gt;, &lt;code&gt;get_precomputed_root_cause&lt;/code&gt;, &lt;code&gt;get_precomputed_spend_analysis&lt;/code&gt;, &lt;code&gt;get_session_value&lt;/code&gt;, &lt;code&gt;set_session_value&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Responsibilities&lt;/strong&gt;: Investigates spend anomalies across two workflows:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Intra-Day (Today’s Spend)&lt;/strong&gt;: Uses real-time Cloud Audit Logs and BigQuery data to discover active services, API invocation counts, caller identities, and operational error anomalies (bypassing GCP Billing ingestion lag).
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Historical Spikes&lt;/strong&gt;: Correlates BigQuery resource-level cost spikes with Cloud Asset Inventory (CAI) configuration change history logs (e.g. machine type upgrades or disk size increases).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s look at the prompt:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;You are the RootCauseAnalyst subagent.
Investigate spend anomalies and intra-day cost drivers by executing either the INTRA-DAY or HISTORICAL workflow based on the user request.

FIRST: Determine the investigation time-frame:
- If the request targets TODAY or real-time cost/spikes, follow the INTRA-DAY WORKFLOW.
- If the request targets a PAST date spike, follow the HISTORICAL WORKFLOW.

INTRA-DAY (TODAY'S COST) INVESTIGATION WORKFLOW:
1. Call `get_today_top_services_and_usage()` FIRST to discover active services today.
2. Extract the top active service names returned (e.g., ["Gemini API", "BigQuery", "Vertex AI", "Cloud Run"]) and pass them into `investigate_today_service_logs(target_services=[...])`.
3. Synthesise intra-day SQL metrics, audit log invocation counts, and caller findings in your final report.
4. INGESTION LATENCY &amp;amp; DISCLOSURE RULE: Always note that standard GCP Billing Export has a 3-12+ hour ingestion delay. If billing partitions show minimal ingested spend while Audit Logs show active calls, report the active invocation counts and state official billing figures are pending.
5. OPERATIONAL ANOMALY RULE: If `has_operational_anomaly == True`, explicitly highlight errors in your summary report and recommend that the user/coordinator run a follow-up diagnosis with `CloudAdvisor`.

HISTORICAL COST SPIKE WORKFLOW (PAST DATES):
1. Identify the single primary spike date (YYYY-MM-DD).
2. Call `get_precomputed_root_cause(date_str="YYYY-MM-DD")` EXACTLY ONCE for that peak date against `{resource_table_id}`.
3. NEVER call `get_precomputed_root_cause` multiple times or loop through multiple dates.
4. Correlate persistent resources with Cloud Asset Inventory (CAI) configuration logs.

CRITICAL: CONCISE SYNTHESIS &amp;amp; TERMINATION
1. Keep the final markdown report under 350 words total.
2. Call `finish_task` and pass the complete final markdown report directly into the `result` parameter, then terminate execution.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are a few key highlights worth calling out in this system prompt:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Explicit Time-Frame Branching&lt;/strong&gt;: The prompt mandates a top-level decision step (&lt;code&gt;TODAY&lt;/code&gt; vs &lt;code&gt;HISTORICAL&lt;/code&gt;) before executing any tools.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Overcoming Ingestion Lag via Audit Logs&lt;/strong&gt;: Standard GCP Billing Exports have a propagation delay, which could be several hours. For intra-day queries, the agent pairs BigQuery partition checks with real-time Cloud Audit Logs (&lt;code&gt;get_today_top_services_and_usage&lt;/code&gt; and &lt;code&gt;investigate_today_service_logs&lt;/code&gt;) to capture active API invocations, caller principal identities, and operational errors in real-time.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Clean Advisory Hand-Off&lt;/strong&gt;: &lt;code&gt;RootCauseAnalyst&lt;/code&gt; focuses purely on log and spend telemetry. It does not contain Gemini Cloud Assist tools directly. When &lt;code&gt;investigate_today_service_logs&lt;/code&gt; detects operational errors (&lt;code&gt;has_operational_anomaly == True&lt;/code&gt;), our agent explicitly recommends that the user or root coordinator run a follow-up diagnostic turn with &lt;code&gt;CloudAdvisor&lt;/code&gt; (which holds the &lt;code&gt;investigate_issue&lt;/code&gt; and &lt;code&gt;ask_cloud_assist&lt;/code&gt; MCP tools).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Okay, that’s it for our overview of the agents. Let’s take a look at how they’re coordinated.&lt;/p&gt;

&lt;h2&gt;
  
  
  Multi-Agent Orchestration Patterns
&lt;/h2&gt;

&lt;p&gt;When designing multi-agent architectures, several standard &lt;a href="https://adk.dev/workflows/patterns/" rel="noopener noreferrer"&gt;workflow patterns&lt;/a&gt; exist for how we can coordinate them. Here are just some of those patterns:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Coordinator-Dispatcher&lt;/strong&gt;: A central root agent acts as an intelligent router, delegating tasks to dedicated subagents based on intent. The root agent makes the decisions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sequential Pipeline&lt;/strong&gt;: Output from Agent A is piped sequentially into Agent B, then Agent C (like an ETL pipeline). Here we use deterministic workflow agents, so a model is not actually making any routing decisions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Parallel Fan-Out and Gather&lt;/strong&gt;: Multiple agents run in parallel, and their results are gathered together at the end. Again, this uses deterministic workflow agents.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Graph-Based Agent Workflows&lt;/strong&gt;: where each agent is a node in a graph, and complex routing between agents is defined declaratively. This is a routing pattern that was introduced with ADK 2.x.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For &lt;em&gt;FinSavant&lt;/em&gt;, we selected the &lt;strong&gt;Coordinator-Dispatcher&lt;/strong&gt; pattern. We give the root agent (our coordinator) a bunch of subagents, and let the root agent decide which agent to delegate to, based on the user’s latest prompt and the information that has already been gathered in the session.&lt;/p&gt;

&lt;p&gt;I should also mention the &lt;a href="https://adk.dev/workflows/collaboration/" rel="noopener noreferrer"&gt;collaboration modes&lt;/a&gt; used by each agent. These determine the behaviour of a subagent that has been delegated to. There are three modes we can choose from:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Chat&lt;/strong&gt;: Full user interaction. I.e. the user can continue to have a conversation with that subagent, and control only returns to the calling agent when a specific criterion (such as an instruction from the user) is met.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Task&lt;/strong&gt;: Here, the subagent performs a specific task, but is allowed to seek clarification from the user in order to complete it. Once the task is complete, control returns to the calling agent.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Single-turn&lt;/strong&gt;: Here, the subagent simply performs a task, but is not allowed to interact with the user. Control returns immediately back to the calling agent. This is useful for asynchronous workflows, such as when calling multiple subagents in parallel.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;code&gt;mode&lt;/code&gt; is defined as a property as part of each subagent definition. So we've got:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;BillingExplorer&lt;/code&gt;: &lt;code&gt;task&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;InfrastructureAuditor&lt;/code&gt;: &lt;code&gt;task&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;CloudAdvisor&lt;/code&gt;: &lt;code&gt;task&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;KnowledgeAssistant&lt;/code&gt;: &lt;code&gt;single_turn&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;RootCauseAnalyst&lt;/code&gt;: &lt;code&gt;task&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You can see that all of our subagents ultimately return control back to the coordinator. And you can also see — in our agent definitions — that I explicitly prohibit subagents handing off to a peer. They must return to the calling orchestrator agent.&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing with ADK UI Tools
&lt;/h2&gt;

&lt;p&gt;Now we’ve got our root agent, subagents and tools defined, we’ve got enough to try it out.&lt;/p&gt;

&lt;p&gt;A great thing about using ADK is that we don’t even need to build a UI to test our agents! We can just use the out-of-the-box developer UIs, like &lt;strong&gt;ADK CLI&lt;/strong&gt; and &lt;strong&gt;ADK Web&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;ADK CLI is a command-line interface intended for easy text-only chats with our agent. For &lt;em&gt;FinSavant&lt;/em&gt;, we can launch it like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;uv run adk run agent/finops_agent
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And then you can issue prompts to the agent, like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7k0xqfna1nuzqlds100d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7k0xqfna1nuzqlds100d.png" alt="ADK CLI" width="777" height="279"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let’s ask it what’s driving my costs over the last 30 days…&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdi60sjacy7o4q6zt02cd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdi60sjacy7o4q6zt02cd.png" alt="ADK CLI question" width="784" height="284"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;(Just type &lt;code&gt;exit&lt;/code&gt; when you're done.)&lt;/p&gt;

&lt;p&gt;This is okay, but we can do much better! We can use &lt;a href="https://adk.dev/runtime/web-interface/" rel="noopener noreferrer"&gt;ADK Web&lt;/a&gt;, a rich web UI that gives us loads of insights into what our agents are doing.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;uv run adk web agent/finops_agent
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By the way, this is a convenient time to add a shortcut to our &lt;code&gt;Makefile&lt;/code&gt;, so we don't have to remember these ADK commands! If you followed my setup guidance from the previous part, this might already be in your &lt;code&gt;Makefile&lt;/code&gt;. But if not, go ahead and add this target:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="c"&gt;# Launch local ADK Web dev playground
&lt;/span&gt;&lt;span class="nl"&gt;playground&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"======================================================="&lt;/span&gt;
    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"| 🚀 Starting your agent playground... |"&lt;/span&gt;
    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"======================================================="&lt;/span&gt;
    uv run adk web agent/finops_agent &lt;span class="nt"&gt;--port&lt;/span&gt; 8501 &lt;span class="nt"&gt;--reload_agents&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The ADK Web UI launches at &lt;code&gt;http://localhost:8000&lt;/code&gt;. And it looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fsk9pn0bwkxzjfbpinids.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fsk9pn0bwkxzjfbpinids.png" alt="ADK Web" width="799" height="475"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There’s so much cool stuff you can see and do from here. For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We can see which agents and tools are currently being invoked.&lt;/li&gt;
&lt;li&gt;We can view our request and response payloads, including the exact prompts that were issued to the agent.&lt;/li&gt;
&lt;li&gt;We can view event metadata, such as number of input and output tokens consumed.&lt;/li&gt;
&lt;li&gt;We can view the agent state.&lt;/li&gt;
&lt;li&gt;We can even build and run evaluation sets. (More on this in a future blog.)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I’ll issue the same “30 day” prompt that we used before.&lt;/p&gt;

&lt;p&gt;Immediately, we get to see a load of useful real-time information. The first thing we see are the state changes, such as which sub-agents and tools are being called:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fivfarp4mdljsaf05zt4p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fivfarp4mdljsaf05zt4p.png" alt="ADK Web state changes" width="799" height="282"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can even view a dynamic visual graph, which reflects whatever event (e.g. request or response) we currently have highlighted:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3oiuj0zgn9z05enn5pt7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3oiuj0zgn9z05enn5pt7.png" alt="ADK event graph view" width="799" height="358"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Of course, we’ve still got our terminal logs:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F54d1f65dkpclglie3v1r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F54d1f65dkpclglie3v1r.png" alt="ADK session terminal logs" width="781" height="247"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And this is super-cool… We can even see a trace view in &lt;code&gt;ADK Web&lt;/code&gt;, that shows a breakdown of the durations of each call:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fe7dn7ba83ypm0y0vt4zw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fe7dn7ba83ypm0y0vt4zw.png" alt="ADK trace" width="800" height="718"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once upon a time, it was difficult to know what calls were causing our multi-agent solution to be slow. No longer!!&lt;/p&gt;

&lt;h2&gt;
  
  
  Performance Optimisation Lessons Learned
&lt;/h2&gt;

&lt;p&gt;Speaking of slow, let me share a couple of key moments in my &lt;em&gt;FinSavant&lt;/em&gt; optimisation journey. I made dozens of performance optimisations, but I’ll just share a couple of the most impactful ones.&lt;/p&gt;

&lt;h3&gt;
  
  
  Partition Pruning &amp;amp; Predicate Pushdown
&lt;/h3&gt;

&lt;p&gt;Standard Google Cloud Billing export tables in BigQuery are partitioned by &lt;code&gt;export_time&lt;/code&gt;. However, if an agent generates an outer SQL query with temporal filters wrapped around an un-scoped inner subquery, BigQuery ends up scanning the entire multi-gigabyte historical dataset before filtering the results!&lt;/p&gt;

&lt;p&gt;To fix this, our BigQuery tool wrapper (&lt;code&gt;execute_cached_bigquery_sql&lt;/code&gt;) dynamically parses temporal constraints (&lt;code&gt;export_time&lt;/code&gt;, &lt;code&gt;usage_start_time&lt;/code&gt;, &lt;code&gt;usage_end_time&lt;/code&gt;) from the agent's SQL query and &lt;strong&gt;pushes down the predicates&lt;/strong&gt; directly into the inner scoping subqueries:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="nv"&gt;`gcp_billing_export_v1_*`&lt;/span&gt; 
  &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;project&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="k"&gt;IN&lt;/span&gt; &lt;span class="p"&gt;(...)&lt;/span&gt; 
    &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;export_time&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="nb"&gt;TIMESTAMP&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DATE_SUB&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;CURRENT_DATE&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;INTERVAL&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt; &lt;span class="k"&gt;DAY&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;usage_start_time&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="nb"&gt;TIMESTAMP&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DATE_SUB&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;CURRENT_DATE&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;INTERVAL&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt; &lt;span class="k"&gt;DAY&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why is predicate pushdown so powerful?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;By moving the date filters directly into the inner table scan, BigQuery performs &lt;em&gt;partition pruning&lt;/em&gt; right at the start. It reads &lt;em&gt;only&lt;/em&gt; the specific disk partitions containing data for the requested time window (e.g. the last 30 days), completely skipping possibly years of irrelevant historical data.&lt;/p&gt;

&lt;p&gt;This results in queries that are much faster and much cheaper! For me, the total time taken by the subagent was trimmed from over a minute to a few seconds.&lt;/p&gt;

&lt;h3&gt;
  
  
  Deterministic Python Precomputation &amp;amp; Subagent Tool Stripping
&lt;/h3&gt;

&lt;p&gt;Rather than having LLM subagents generate complex SQL queries, inspect raw data rows, and run multi-turn self-correction loops, I implemented native Python precomputation tools, like &lt;code&gt;get_precomputed_spend_analysis&lt;/code&gt; and &lt;code&gt;get_precomputed_root_cause&lt;/code&gt;. Why do this?&lt;/p&gt;

&lt;p&gt;Well…&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Dynamically writing SQL queries is slow, non-deterministic, and often requires loops if the initial SQL queries are incorrect.&lt;/li&gt;
&lt;li&gt;And, getting the agent to do this work is costly! It’s a waste of tokens.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If we know exactly what we need the agent to do in a given step, and we can code in a deterministic way, &lt;strong&gt;THEN WE SHOULD&lt;/strong&gt;. Don’t use LLMs to dynamically work out how to do stuff you already know how to do. That’s a poor way to use AI!&lt;/p&gt;

&lt;p&gt;Across all our agents, this change was probably the most significant time and token saver, overall.&lt;/p&gt;

&lt;h2&gt;
  
  
  Test-Driven Development &amp;amp; Unit Testing
&lt;/h2&gt;

&lt;p&gt;Of course, I created unit tests. I say &lt;em&gt;“I created unit tests”&lt;/em&gt;, but in reality, I got Antigravity to build most of them for me. But these proved extremely useful in catching issues and preventing regressions.&lt;/p&gt;

&lt;p&gt;At the time of writing, I have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;80 unit tests across 13 modules&lt;/li&gt;
&lt;li&gt;5 integration tests across 3 modules&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I run them with &lt;code&gt;make test&lt;/code&gt;, using these targets in my &lt;code&gt;Makefile&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="c"&gt;# Run unit tests
&lt;/span&gt;&lt;span class="nl"&gt;test&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    uv &lt;span class="nb"&gt;sync&lt;/span&gt; &lt;span class="nt"&gt;--dev&lt;/span&gt;
    uv run pytest tests/unit

&lt;span class="c"&gt;# Run unit and integration tests
&lt;/span&gt;&lt;span class="nl"&gt;test-all&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    uv &lt;span class="nb"&gt;sync&lt;/span&gt; &lt;span class="nt"&gt;--dev&lt;/span&gt;
    uv run pytest tests/unit &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; uv run pytest tests/integration
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I also have these tests integrated into my GitHub Actions CI/CD pipeline. (I’ll cover this in a future part.)&lt;/p&gt;

&lt;h2&gt;
  
  
  Building the FastAPI Backend-for-Frontend (BFF)
&lt;/h2&gt;

&lt;p&gt;This part of the series is mainly about the agentic parts of the solution, so I won’t go into a lot of detail about the BFF itself. But I’ll cover it briefly, so you’ve got an understanding of how our UI will interact with the agentic layer.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is a BFF and Why Do We Need It?
&lt;/h3&gt;

&lt;p&gt;A &lt;strong&gt;Backend-for-Frontend (BFF)&lt;/strong&gt; is an architectural pattern where a dedicated server-side application acts as an intermediary (a kind of proxy) between the client frontend (our React UI) and backend services, such as our agents. Rather than having the browser React application talk directly to GCP APIs or remote Agent Runtime endpoints, the BFF handles all the heavy lifting behind the scenes.&lt;/p&gt;

&lt;p&gt;In &lt;em&gt;FinSavant&lt;/em&gt;, the BFF is doing (amongst other things) the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Protocol &amp;amp; Stream Formatting&lt;/strong&gt;: Formats raw agent event streams and tool calls into clean Server-Sent Events (SSE) for the React frontend.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rate Limiting &amp;amp; Protection&lt;/strong&gt;: Enforces per-user rate limits (via &lt;code&gt;SlowAPI&lt;/code&gt;) to prevent denial-of-wallet API spikes.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  What is FastAPI and Why Have We Used It?
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://fastapi.tiangolo.com/" rel="noopener noreferrer"&gt;FastAPI&lt;/a&gt; is a modern, high-performance Python API framework. It’s basically the gold standard for building APIs in Python these days. And Google ADK provides a native FastAPI helper (&lt;code&gt;get_fast_api_app&lt;/code&gt;), making it simple to bind ADK runners, session storage, and A2A routes.&lt;/p&gt;

&lt;p&gt;Let’s look at how the BFF (&lt;code&gt;bff/fast_api_app.py&lt;/code&gt;) interacts with our agent layer...&lt;/p&gt;

&lt;h3&gt;
  
  
  Defining the FastAPI App
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;FastAPI&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_fast_api_app&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;agents_dir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;AGENT_DIR&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;web&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;artifact_service_uri&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ARTIFACT_SERVICE_URI&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;allow_origins&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;allow_origins&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;session_service_uri&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SESSION_SERVICE_URI&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;otel_to_cloud&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;otel_to_cloud&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;lifespan&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;lifespan&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;smart-gcp-finops-bff&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;description&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;BFF API for interacting with the FinOps Agent&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;limiter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;limiter&lt;/span&gt;
&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_middleware&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SlowAPIMiddleware&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_exception_handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;RateLimitExceeded&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_rate_limit_exceeded_handler&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note the &lt;strong&gt;&lt;code&gt;web=False&lt;/code&gt;&lt;/strong&gt; setting. By default, ADK's &lt;code&gt;get_fast_api_app&lt;/code&gt; helper sets &lt;code&gt;web=True&lt;/code&gt;, which automatically mounts ADK's built-in developer playground UI at the root (&lt;code&gt;/&lt;/code&gt;) path. Since our BFF container serves our custom React SPA in production, setting &lt;code&gt;web=False&lt;/code&gt; is essential. Without this, ADK's default playground (i.e. the ADK Web UI) overrides the root route.&lt;/p&gt;

&lt;p&gt;The BFF automatically detects its runtime environment at startup. In local dev mode, it runs a standard in-process ADK &lt;code&gt;Runner&lt;/code&gt;. In production on Cloud Run, it switches to "remote mode" and routes requests directly to &lt;strong&gt;Gemini Enterprise Agent Platform Agent Runtime&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nd"&gt;@contextlib.asynccontextmanager&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;lifespan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;FastAPI&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;AsyncIterator&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
    &lt;span class="n"&gt;agent_runtime_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;AGENT_RUNTIME_ID&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;agent_runtime_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# Local development mode: run agent in-process via ADK Runner
&lt;/span&gt;        &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;finops_agent.agent&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;adk_app&lt;/span&gt;
        &lt;span class="n"&gt;runner&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Runner&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;adk_app&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;session_service&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_session_service&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
            &lt;span class="n"&gt;artifact_service&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_artifact_service&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;runner&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;runner&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# Production mode: agent runs remotely on Agent Runtime
&lt;/span&gt;        &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;runner&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;

    &lt;span class="k"&gt;yield&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Streaming Agent Events over SSE (&lt;code&gt;/api/chat/stream&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;When a user submits a prompt, the React frontend calls &lt;code&gt;/api/chat/stream&lt;/code&gt;. The BFF resolves the authenticated user's project permissions, sets contextual state variables (&lt;code&gt;ALLOWED_PROJECTS_VAR&lt;/code&gt;), invokes the agent, and streams back thought logs, friendly tool names, and A2UI payloads in real time:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nd"&gt;@app.post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/api/chat/stream&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nd"&gt;@limiter.limit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chat_rate_limit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;chat_stream&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;user_email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;_get_user_email&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;allowed_projects&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_user_accessible_projects&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_email&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Scope execution context to projects this user is authorised to query
&lt;/span&gt;    &lt;span class="n"&gt;token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ALLOWED_PROJECTS_VAR&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;allowed_projects&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;event_generator&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="c1"&gt;# Stream thought logs, tool execution badges, and final text/A2UI payloads
&lt;/span&gt;        &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;run_agent_stream&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user_prompt&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;data: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;StreamingResponse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;event_generator&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;media_type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text/event-stream&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This ensures the React frontend receives real-time progress updates. For details of what this looks like... You’ll have to wait until the next part!&lt;/p&gt;

&lt;h3&gt;
  
  
  Cloud Run Keep-Alive Heartbeats
&lt;/h3&gt;

&lt;p&gt;Cloud Run automatically terminates HTTP connections if no data bytes are transmitted for a few seconds. To prevent connection drops during complex multi-tool agent reasoning flows, our SSE generator emits comment heartbeats every 15 seconds while waiting for agent turn updates:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Stream heartbeats every 15 seconds to prevent Cloud Run connection timeouts
&lt;/span&gt;&lt;span class="n"&gt;seconds_passed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;done&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;seconds_passed&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;seconds_passed&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# SSE comment heartbeat to keep connection alive
&lt;/span&gt;        &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;: heartbeat&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="n"&gt;seconds_passed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  BFF Rate Limiting (&lt;code&gt;slowapi&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;To prevent Denial-of-Wallet attacks and API quota exhaustion, the BFF applies &lt;code&gt;slowapi&lt;/code&gt; rate limiting on some of our endpoints, like &lt;code&gt;/api/chat/stream&lt;/code&gt;, keyed by the user's authenticated identity.&lt;/p&gt;

&lt;h3&gt;
  
  
  Testing the BFF
&lt;/h3&gt;

&lt;p&gt;In the absence of a UI (coming in the next part), we just need to be able to send an HTTP request to our new shiny API. Let’s create a new target in our &lt;code&gt;Makefile&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="c"&gt;# Launch local development server with hot-reload (defaults to local in-process ADK agent mode)
# Usage: make local-backend [PORT=8000] - Specify PORT for parallel scenario testing
&lt;/span&gt;&lt;span class="nl"&gt;local-backend&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="nv"&gt;AGENT_RUNTIME_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt; &lt;span class="nv"&gt;PYTHONPATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;agent uv run uvicorn bff.fast_api_app:app &lt;span class="nt"&gt;--host&lt;/span&gt; 127.0.0.1 &lt;span class="nt"&gt;--port&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;or &lt;span class="p"&gt;$(&lt;/span&gt;PORT&lt;span class="p"&gt;)&lt;/span&gt;,8000&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;--reload&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we can launch the API — which automatically launches the backend agent — with this command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;make local-backend
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fsjapq2o9wnm20sio38m6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fsjapq2o9wnm20sio38m6.png" alt="make local-backend" width="800" height="191"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once that’s running, start a separate terminal session and send some requests to the API with &lt;code&gt;curl&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl http://localhost:8000/api/status
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Firyx77ijnrzcknw45vhv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Firyx77ijnrzcknw45vhv.png" alt="API Status" width="414" height="38"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Or we can issue a prompt, like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-N&lt;/span&gt; &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="s2"&gt;"http://localhost:8000/api/chat/stream"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
   &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
   &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"message": "What is driving my costs over the last 30 days?"}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The response looks a bit horrible, but you get the idea!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhakxph1ifgtt9rjdxjda.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhakxph1ifgtt9rjdxjda.png" alt="API Chat Stream" width="800" height="106"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What’s Next?
&lt;/h2&gt;

&lt;p&gt;With our multi-agent backend, precomputed toolsets, and FastAPI BFF tested and (slightly) optimised, we’re ready to build the user interface!&lt;/p&gt;

&lt;p&gt;In &lt;strong&gt;Part 4&lt;/strong&gt;, we’ll dive into &lt;strong&gt;Designing and Building the UI with Google Stitch and A2UI&lt;/strong&gt;, exploring how we used Google Stitch to craft our dark-mode aesthetic and how A2UI dynamically drives interactive SVG area charts, KPI tiles, and waste optimisation cards on the React canvas.&lt;/p&gt;

&lt;p&gt;Stay tuned!&lt;/p&gt;

&lt;h2&gt;
  
  
  Before You Go
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Please &lt;strong&gt;share this&lt;/strong&gt; with anyone that you think will be interested. It might help them, and it really helps me!&lt;/li&gt;
&lt;li&gt;Please give me loads of &lt;strong&gt;claps&lt;/strong&gt;! (Just hold down the clap button.)&lt;/li&gt;
&lt;li&gt;Please leave a &lt;strong&gt;comment&lt;/strong&gt; 💬. Interaction is good!&lt;/li&gt;
&lt;li&gt;Add a &lt;strong&gt;star&lt;/strong&gt; on the repo!&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Follow and subscribe&lt;/strong&gt;, so you don’t miss my content.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Useful Links and References
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Project Demo &amp;amp; Portfolio
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/derailed-dash/smart-gcp-finops" rel="noopener noreferrer"&gt;FinSavant on GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=zs_IRUxIx4E" rel="noopener noreferrer"&gt;FinSavant YouTube Demo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dazbo.co.uk/" rel="noopener noreferrer"&gt;Dazbo’s Portfolio&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Series Links
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://medium.com/google-cloud/finsavant-part-1-building-an-agentic-finops-platform-with-google-adk-a2ui-and-gemini-enterprise-248f59cea3a0?postPublishedType=repub" rel="noopener noreferrer"&gt;Goals, Architecture, and Tech Stack: Capabilities, project goals, target architecture, technology stack, and design decisions.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/google-cloud/finsavant-part-2-building-an-agentic-finops-platform-development-environment-setup-google-dd12b8b84ba0" rel="noopener noreferrer"&gt;Dev Environment Setup with Google Antigravity, ADK, Agents CLI, MCP &amp;amp; Skills&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Google Cloud Services &amp;amp; APIs
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://blog.google/innovation-and-ai/models-and-research/gemini-models/gemini-3-6-flash-3-5-flash-lite-3-5-flash-cyber/?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;Introducing Gemini 3.6 Flash and 3.5 Flash-Lite&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.cloud.google.com/cloud-assist/overview?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;Google Cloud Assist&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.cloud.google.com/asset-inventory/docs/overview?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;Cloud Asset Inventory (CAI) API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developers.google.com/knowledge/mcp?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;Developer Knowledge MCP Server&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  ADK
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://adk.dev/callbacks/" rel="noopener noreferrer"&gt;ADK Callbacks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://adk.dev/plugins/" rel="noopener noreferrer"&gt;ADK Plugins&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://adk.dev/workflows/patterns/" rel="noopener noreferrer"&gt;ADK Workflow Patterns&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://adk.dev/workflows/collaboration/" rel="noopener noreferrer"&gt;ADK Collaboration Modes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://adk.dev/runtime/web-interface/" rel="noopener noreferrer"&gt;ADK Web&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>finops</category>
      <category>bigqueryoptimization</category>
      <category>agenticai</category>
      <category>multiagentsystems</category>
    </item>
    <item>
      <title>Automated GitHub Code Reviews Using Google Gemini</title>
      <dc:creator>Darren "Dazbo" Lester</dc:creator>
      <pubDate>Thu, 16 Jul 2026 11:16:35 +0000</pubDate>
      <link>https://dev.to/gde/automated-github-code-reviews-using-google-gemini-4l0f</link>
      <guid>https://dev.to/gde/automated-github-code-reviews-using-google-gemini-4l0f</guid>
      <description>&lt;h2&gt;
  
  
  I Built a Thing!
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;TL;DR — Google Gemini-based Pull Request reviews and Issue Triaging for all your GitHub repositories and CI/CD pipelines.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F55qnkoz6h3sanox4lv7u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F55qnkoz6h3sanox4lv7u.png" alt="Automatic code review and issues triage" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What’s the Big Deal?
&lt;/h2&gt;

&lt;p&gt;If you or your fellow developers aren’t yet using AI to automate code reviews, then you’re missing out on an &lt;strong&gt;absolute game-changer&lt;/strong&gt; in the software development lifecycle.&lt;/p&gt;

&lt;p&gt;Legacy approach:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;You commit your code.&lt;/li&gt;
&lt;li&gt;You submit your pull request (PR).&lt;/li&gt;
&lt;li&gt;You wait for another developer to perform a code review and approve the PR.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is the way it’s been for years. It’s fine. But the review process — and the reviewer — becomes a bottleneck. And furthermore, it’s a human process that is subject to significant variability.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Enter automated code reviews.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now, after you submit the PR, a code review is automatically triggered and performed by your favourite model, using whatever instructions and grounding you and your team require. The review happens pretty much immediately. And the quality of the review is often higher than that of your fellow developers.&lt;/p&gt;

&lt;p&gt;For the many colleagues I work with who have switched to this approach, the main benefits are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No waiting for a human review.&lt;/li&gt;
&lt;li&gt;High quality code reviews that not only catch issues, but also provide easy-to-follow recommendations and explanations that help the developer to learn and improve.&lt;/li&gt;
&lt;li&gt;Massive increase in overall development velocity.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;I love it. They love it. You’ll love it too!&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdwvb6lsuvjzxiebkhrco.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdwvb6lsuvjzxiebkhrco.gif" alt="I love it!" width="220" height="220"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  RIP Gemini CLI Actions
&lt;/h2&gt;

&lt;p&gt;For a while, Google gave us this review capability out-of-the-box. We had tools that could read our pull requests, analyse our code diffs, and write constructive, line-specific feedback comments directly on GitHub.&lt;/p&gt;

&lt;p&gt;But then, the music stopped. If you used to rely on Google’s Gemini-based PR review integrations in GitHub, then you’re probably now sobbing into your strawberry daiquiri. (I know I was.)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Feu6lo2g1hl4d8vef4vh7.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Feu6lo2g1hl4d8vef4vh7.gif" alt="Crying into a daiquiri" width="599" height="337"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Specifically, two Google mechanisms that developers loved have been decommissioned:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Gemini CLI GitHub Actions (&lt;code&gt;run-gemini-cli&lt;/code&gt;)&lt;/strong&gt;
This was a GitHub Action that you could easily integrate into your GitHub repos by running a &lt;code&gt;/setup-github&lt;/code&gt; command from within Google Gemini CLI. Once installed, this action would spin up a container running Gemini CLI, and use it to perform automated reviews of your code in response to a pull request. Alas, this mechanism stopped serving requests on &lt;strong&gt;June 18, 2026&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gemini Code Assist on GitHub&lt;/strong&gt;
This direct GitHub App integration relied on Google Gemini Code Assist. Whenever a pull request was opened, GitHub sent a webhook to Google’s backend. This has also been shut down as of &lt;strong&gt;July 17, 2026&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;But why have they gone? It’s because Google has terminated both Gemini Code Assist and Gemini CLI in favour of the newer &lt;a href="https://antigravity.google/?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;Google Antigravity suite&lt;/a&gt;. This is true even for users on a paid Google AI subscription.&lt;/p&gt;

&lt;p&gt;What can you do if you relied on these tools? What can you migrate to?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fes3na9h9kfunuvh4drml.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fes3na9h9kfunuvh4drml.gif" alt="I’m so glad you asked!" width="480" height="267"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Answer: My Super-Fast Drop-In Replacement
&lt;/h2&gt;

&lt;p&gt;I didn’t want to lose my automated PR reviews. So, I built a drop-in replacement: the &lt;strong&gt;Gemini PR Review &amp;amp; Triage Action&lt;/strong&gt; (&lt;a href="https://github.com/derailed-dash/gemini-review-action" rel="noopener noreferrer"&gt;derailed-dash/gemini-review-action&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7s2uh0o3jm9j1ikglv49.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7s2uh0o3jm9j1ikglv49.png" alt="Dazbo’s Gemini PR Review &amp;amp; Triage Action" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I’ve officially published this to the &lt;a href="https://github.com/marketplace/actions/dazbo-s-gemini-review-triage" rel="noopener noreferrer"&gt;GitHub Marketplace&lt;/a&gt; too, so you can find it indexed there and enjoy nice IDE autocompletion when configuring your workflows!&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Features Overview
&lt;/h2&gt;

&lt;p&gt;Here’s a quick summary of what it does…&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fu11udkhoxvenaivzod3g.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fu11udkhoxvenaivzod3g.jpeg" alt="Features" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;AI-Powered Code Reviews&lt;/strong&gt;: Automated, constructive line-specific feedback on Pull Requests using Google Gemini models (Gemini 3.6 Flash by default).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automated Issue Triage&lt;/strong&gt;: Dynamically labels, prioritises, and triages incoming issues.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Drop-in Migration&lt;/strong&gt;: Fully compatible as a direct, drop-in replacement for the deprecated &lt;code&gt;run-gemini-cli&lt;/code&gt; action.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Structured Outputs&lt;/strong&gt;: Error-free JSON response formatting using Pydantic schema validation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hybrid Codebase Context&lt;/strong&gt;: Automatically includes codebase context based on the overall size of the codebase. If the codebase isn't huge, the entire repo is loaded into context; but if it is huge, the agent reads the overall directory tree and judiciously includes a subset of the repo. (Note that it always reads markdown files, dependency files, packaging files, etc.)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PR Comment &amp;amp; Discussion Thread History&lt;/strong&gt;: Automatically retrieves inline review threads and general PR conversation comments, enabling Gemini to track issue resolution, respect developer justifications/disagreements, and avoid repeating resolved suggestions across commits.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tokenomics &amp;amp; Cost Telemetry Report&lt;/strong&gt;: Appends a collapsible cost efficiency and token usage summary to each review.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Interactive Suggestions&lt;/strong&gt;: Formats code recommendations inside native GitHub &lt;code&gt;&lt;/code&gt;`&lt;code&gt;suggestion&lt;/code&gt; blocks for one-click merge applications.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Triggers&lt;/strong&gt;: The action triggers automatically in response to PR events. It can also be triggered by posting a comment in the PR starting with &lt;code&gt;/gemini-review&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fast-Execution Composite Action&lt;/strong&gt;: Avoids containerisation build/pull latency (no slow &lt;code&gt;docker build&lt;/code&gt; on every execution) by running as a native composite action.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cross-Platform Support&lt;/strong&gt;: Runs natively on Linux, macOS, and Windows runners (both GitHub-hosted and self-hosted).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Modern SDK Execution&lt;/strong&gt;: Leverages the modern Google GenAI SDK (&lt;code&gt;google-genai&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enterprise-Grade Security&lt;/strong&gt;: Authentication via either Google Gemini API Keys or Google Cloud Workload Identity Federation (WIF).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Customisable Prompts&lt;/strong&gt;: Supports repository-specific overrides for both reviews and triaging via simple TOML config files.&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Reviewer Personas&lt;/strong&gt;: Customise the personality, tone, and review style of the agent with pre-built persona overlays (&lt;code&gt;straight&lt;/code&gt;, &lt;code&gt;dazbo&lt;/code&gt;, &lt;code&gt;palpatine&lt;/code&gt;, &lt;code&gt;rick&lt;/code&gt;).&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fuvcl7m139mijtdl9bd7k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fuvcl7m139mijtdl9bd7k.png" alt="Rick Persona" width="800" height="454"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Google Developer Knowledge Integration&lt;/strong&gt;: Automatically queries official Google developer documentation (Google Cloud, Firebase, Android, etc.) via MCP to cross-reference your changes against up-to-date best practices.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;On-Demand Agent Skills&lt;/strong&gt;: Dynamically discovers and loads project-specific formatting guidelines and coding standards from &lt;code&gt;.agents/skills&lt;/code&gt; on-demand, keeping prompt contexts lightweight and relevant (bundled with defaults for Google Cloud, Gemini APIs and agentic development).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Gemini Context Caching&lt;/strong&gt;: Native, automatic integration with Gemini Context Caching, delivering up to &lt;strong&gt;90% cost reduction&lt;/strong&gt; on input tokens for repositories over 32k tokens.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Multi-Turn &amp;amp; Cross-PR Cache Reuse&lt;/strong&gt;: Reuses active server-side context cache handles across multi-turn tool/skill calls and successive PR pushes within the TTL window (1h default), eliminating prompt re-tokenisation and server overhead. This is a huge efficiency and cost saving between successive reviews.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Rationale and Design Decisions
&lt;/h2&gt;

&lt;p&gt;Before I built my own, I started by looking at the open source community and found a couple of replacements in the ecosystem. But they didn’t quite tick all my boxes.&lt;/p&gt;

&lt;p&gt;Here are some reasons why I built it, and some of the design decisions I made along the way…&lt;/p&gt;

&lt;h3&gt;
  
  
  Performance — Native Composite Actions with &lt;code&gt;uv&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;The community versions I found installed their Python dependencies using &lt;code&gt;pip&lt;/code&gt;. This is fine, but it’s very slow compared to Astral’s awesome &lt;code&gt;uv&lt;/code&gt;. So I wanted to build a solution that’s much faster. If you ever found yourself making changes and then re-running your code review, you’ll appreciate the frustration!&lt;/p&gt;

&lt;p&gt;Instead of packaging the action inside a slow Docker container (like &lt;code&gt;run-gemini-cli&lt;/code&gt; did), I designed it as a native &lt;strong&gt;composite action&lt;/strong&gt; leveraging &lt;strong&gt;&lt;code&gt;uv&lt;/code&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Because &lt;code&gt;uv&lt;/code&gt; handles virtual environments and package installations with blazing speed, the scripts start running almost instantly. No Docker pulls, no container builds, and no slow &lt;code&gt;pip&lt;/code&gt; resolution phases. The reviews execute in seconds, saving you valuable runner minutes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Binary Fragility and Codebase Context
&lt;/h3&gt;

&lt;p&gt;The community integrations I tried were a little fragile when processing binary files or encrypted assets, and they completely lacked project-wide context. They could only see the raw diff. I needed a solution that was resilient and understood the broader codebase.&lt;/p&gt;

&lt;p&gt;My action parses the diff and automatically filters out binary, compressed, or encrypted assets. For the remaining text files, it implements a smart &lt;strong&gt;hybrid codebase context engine&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Full Context Mode&lt;/strong&gt;: For smaller codebases (less than 1.5MB, excluding the stuff we filtered out), the action automatically attaches the full contents of all other files in the repository. Gemini gains complete project-wide awareness.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sparse Context Mode&lt;/strong&gt;: For larger codebases, it switches to a sparse mode. It attaches a visual file directory structure of the repository, plus the full contents of core manifest/configuration files and markdown documentation. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This ensures Gemini understands exactly how your PR changes fit into the overall project structure, resulting in significantly higher quality feedback.&lt;/p&gt;

&lt;h3&gt;
  
  
  JSON Schema Enforcement
&lt;/h3&gt;

&lt;p&gt;Asking a model to return JSON in a text prompt is always a gamble. Without using Gemini’s native &lt;code&gt;response_schema&lt;/code&gt; API (which forces structure via Pydantic model validation), the model can return markdown-wrapped JSON or invalid formats, breaking the comment parser. Again, another source of fragility.&lt;/p&gt;

&lt;p&gt;My solution addresses this using &lt;strong&gt;structured outputs&lt;/strong&gt; with strict Pydantic schemas.&lt;/p&gt;

&lt;h3&gt;
  
  
  SDK &amp;amp; Model Defaults
&lt;/h3&gt;

&lt;p&gt;Alternatives I found were using older deprecated SDKs like &lt;code&gt;google-generativeai&lt;/code&gt;, and legacy AI models like &lt;code&gt;gemini-2.5-pro&lt;/code&gt;. I wanted to use the more up-to-date &lt;code&gt;google-genai&lt;/code&gt; SDK, and default to the latest and greatest &lt;code&gt;gemini-3.6-flash&lt;/code&gt; right out of the box. It’s so much better at code reviews than the older models, and so much faster too!&lt;/p&gt;

&lt;h3&gt;
  
  
  Configurable Language
&lt;/h3&gt;

&lt;p&gt;The community actions I found didn’t offer a way to configure the preferred review language and sometimes the response was being returned to me in a language I couldn’t read! So I wanted the ability to configure (amongst other things) the review language.&lt;/p&gt;

&lt;h3&gt;
  
  
  Upgraded Intelligence: On-Demand Skills &amp;amp; Official Google Developer Knowledge MCP
&lt;/h3&gt;

&lt;p&gt;I think you're gonna love this one!&lt;/p&gt;

&lt;p&gt;A code reviewer is only as good as the standards and documentation it references. Historically, enforcing custom style guides or keeping up with changing APIs meant cramming thousands of lines of documentation directly into the system instructions, wasting tokens and confusing the model. &lt;/p&gt;

&lt;p&gt;So my reviewer includes real-time, context-aware intelligence:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkioie3nlhlmah2b17zw6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkioie3nlhlmah2b17zw6.png" alt="Context with skills and Google Developer Knowledge" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Google Developer Knowledge MCP (Out-of-the-Box)&lt;/strong&gt;: If your &lt;code&gt;GEMINI_API_KEY&lt;/code&gt; (or Google Cloud Application Default Credentials) has the Developer Knowledge API enabled, the reviewer automatically registers the Developer Knowledge MCP. When it reviews PR code related to Google Cloud services (GKE, Cloud Run, Cloud Logging), Firebase, Android, or Google APIs, the model dynamically calls search tools to cross-reference your changes against official, up-to-date Google best practices in real-time!&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;On-Demand Agent Skills Registry&lt;/strong&gt;: You can now add additional knowledge, custom style guides, API rules, or release standards by adding "skills" markdown files inside &lt;code&gt;.agents/skills/&lt;/code&gt; (e.g. &lt;code&gt;.agents/skills/my-react-rules/SKILL.md&lt;/code&gt;). The reviewer checks for available skills when it starts up, and only activates specific skills that are relevant for the current review. This keeps our context lightweight. Plus, this action comes pre-packaged with a default set of skills for Google Cloud, Gemini APIs, and agentic development.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Best Practices Alignment&lt;/strong&gt;: By combining official Google Developer Knowledge MCP tools with local workspace skills, the reviewer is primed out-of-the-box to ensure your code matches real-world, industry-standard best practices.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Clean Slate Reviews (No Session Bias)
&lt;/h2&gt;

&lt;p&gt;When you're pair-programming or debugging with a local AI assistant, it builds up a massive conversational history. While that context is brilliant for generating code, it also introduces a subtle problem: &lt;strong&gt;session bias&lt;/strong&gt;. The local agent knows the evolutionary journey of your code, what compromises you discussed, and what you intended to do. It understands your intent so well that it can become overly forgiving, overlooking gaps or regressions in the final implementation.&lt;/p&gt;

&lt;p&gt;This GitHub Action, by contrast, starts with a completely clean slate. It has no idea how you arrived at your solution, what you struggled with, or what you discussed with your local IDE assistant. It is a stateless, objective reviewer checking the actual diff against the codebase. This means it often catches bugs, edge cases, or security issues that your local assistant completely glossed over!&lt;/p&gt;

&lt;h2&gt;
  
  
  A Quick Primer: What are GitHub Actions?
&lt;/h2&gt;

&lt;p&gt;Before we start throwing a YAML configuration at your repository, let’s make sure we’re on the same page. If you already know your way around CI/CD in GitHub, feel free to skip this bit.&lt;/p&gt;

&lt;p&gt;GitHub Actions are GitHub’s native automation platform. Instead of running and maintaining external build servers — I’m looking at you, Jenkins (&lt;em&gt;shudder&lt;/em&gt;) — it allows us to run automated pipelines directly inside your repository in response to events like a code push, a new Pull Request, or even someone leaving a comment.&lt;/p&gt;

&lt;p&gt;Here’s the basic vocabulary:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Workflows&lt;/strong&gt; : The overall automated process, defined in a YAML file inside your &lt;code&gt;.github/workflows/&lt;/code&gt; directory.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Events/Triggers&lt;/strong&gt; : The GitHub occurrences that kick off the workflow (e.g. &lt;code&gt;pull_request&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Runners&lt;/strong&gt; : The virtual machines (hosted by GitHub or self-hosted) that execute the jobs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Jobs&lt;/strong&gt; : A collection of steps that run sequentially on the same runner.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Steps&lt;/strong&gt; : Individual tasks that either run commands or use &lt;strong&gt;GitHub Actions&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Actions&lt;/strong&gt; : Reusable plugins (like ours!) that do the heavy lifting, saving you from writing your own scripts.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It all hangs together like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fn4qg0kxml613tn579tlp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fn4qg0kxml613tn579tlp.png" alt="GitHub Actions explained" width="700" height="523"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting It Up in 3 Minutes
&lt;/h2&gt;

&lt;p&gt;Now you know what a GitHub Action is. Let me walk you through how to bring my GitHub Action into your own repository.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Authentication (Required for Both Methods)
&lt;/h3&gt;

&lt;p&gt;Before you install any workflows, you need a one-time authentication setup for your repository so the action can authenticate with the Google Gemini API. You have two choices:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;The Easy Route:&lt;/strong&gt; Generate a Gemini API Key in &lt;a href="https://aistudio.google.com/?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;Google AI Studio&lt;/a&gt;. In GitHub, navigate to &lt;strong&gt;Settings&lt;/strong&gt; &amp;gt; &lt;strong&gt;Secrets and variables&lt;/strong&gt; &amp;gt; &lt;strong&gt;Actions&lt;/strong&gt;, click &lt;strong&gt;New repository secret&lt;/strong&gt;, and add your key named &lt;strong&gt;&lt;code&gt;GEMINI_API_KEY&lt;/code&gt;&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Enterprise Way:&lt;/strong&gt; If you are running in a corporate Google Cloud environment, you can use &lt;strong&gt;Workload Identity Federation (WIF)&lt;/strong&gt; and Application Default Credentials (ADC) to authenticate securely without storing static secrets. See the &lt;a href="https://github.com/derailed-dash/gemini-review-action" rel="noopener noreferrer"&gt;repository&lt;/a&gt; for WIF setup instructions.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Step 2: Install the Workflows
&lt;/h3&gt;

&lt;p&gt;Once authentication is configured, choose one of the two options below to add the workflow files to your repository.&lt;/p&gt;

&lt;h4&gt;
  
  
  Option A: The Ultra-Lazy Route (Install via Agent Skill)
&lt;/h4&gt;

&lt;p&gt;If you are already using an agentic coding environment like Google Antigravity, you don't even need to copy and paste the YAML configuration files manually. You can use my skill repository to automate the setup!&lt;/p&gt;

&lt;p&gt;Simply run the following command in your terminal to install the skill locally:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npx skills add https://github.com/derailed-dash/dazbo-agent-skills -y -g --skill install-gemini-code-review-action&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Once installed, you can just tell your AI coding assistant:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Install the Gemini code review action in this repo."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The skill will run an interactive setup checklist:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Detects and removes legacy actions&lt;/strong&gt; (like &lt;code&gt;run-gemini-cli&lt;/code&gt;) that might conflict.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prompts you for your preferences&lt;/strong&gt; (e.g. if you want both PR Review and Issue Triage, your preferred review language, and model).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Writes the workflow &lt;code&gt;.yml&lt;/code&gt; files&lt;/strong&gt; and custom prompt &lt;code&gt;.toml&lt;/code&gt; templates.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Offers to commit and push&lt;/strong&gt; the changes directly to your repository!&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Option B: The Manual Route
&lt;/h4&gt;

&lt;p&gt;If you prefer to set it up manually, it’s still very easy! Create a file in your repository called &lt;code&gt;.github/workflows/gemini-review.yml&lt;/code&gt; and paste in the sample configuration.&lt;/p&gt;

&lt;p&gt;You don’t need to change this config at all, but you can if you want to. The part you’re most likely to want to modify is the inclusions and exclusions. There are other configurations you can tweak here, and the &lt;a href="https://github.com/derailed-dash/gemini-review-action" rel="noopener noreferrer"&gt;repo&lt;/a&gt; provides more details.&lt;/p&gt;

&lt;p&gt;After you add the workflow to your own repo, it will look something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fuqaki5vwzfwktq6gynli.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fuqaki5vwzfwktq6gynli.png" alt="gemini-review.yml included in your repo" width="800" height="358"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: [Optional] Customise the AI’s Personality
&lt;/h3&gt;

&lt;p&gt;You don’t have to stick to the default prompt. But I suggest you do — there’s a lot of smarts built into the default. But I recommend you always start by copying the defaults located in the &lt;code&gt;starter-examples/&lt;/code&gt; directory of the project.&lt;/p&gt;

&lt;h2&gt;
  
  
  Let’s See It Run!
&lt;/h2&gt;

&lt;p&gt;Let’s do a quick demo. For this demo, the action has already been installed our repo.&lt;/p&gt;

&lt;p&gt;Then we create a PR:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fh8w9ynqls8fw0bxbo3ci.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fh8w9ynqls8fw0bxbo3ci.png" alt="Create a PR" width="789" height="711"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In a couple of seconds we’ll see the workflow begin to run:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fphwnkn17l9t2aygjmrnl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fphwnkn17l9t2aygjmrnl.png" alt="Workflow is running" width="772" height="632"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A few seconds later, the review completes and we see the recommendations:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7moxmvkz2d44r64n37wx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7moxmvkz2d44r64n37wx.png" alt="Review complete" width="800" height="747"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Triggering a Review with a Comment
&lt;/h2&gt;

&lt;p&gt;We’ve seen the review trigger in response to creating a PR. But we can also trigger a PR by adding a GitHub comment: &lt;code&gt;/gemini-review&lt;/code&gt;. This is really useful for re-running a review on-demand. (Again, this is a feature that existed in the original Google tools, and I wanted to keep it.)&lt;/p&gt;

&lt;p&gt;Under-the-hood, my workflow achieves this using the &lt;code&gt;issue_comment&lt;/code&gt; trigger.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Notice the &lt;code&gt;if&lt;/code&gt; conditional for &lt;code&gt;issue_comment&lt;/code&gt;. This is incredibly important. On public repositories, anyone can leave a comment on a Pull Request. Without that &lt;code&gt;author_association&lt;/code&gt; check, a random internet stranger could comment &lt;code&gt;/gemini-review&lt;/code&gt; on your PR and drain your Gemini API quota — not to mention your GitHub Action runner minutes. By restricting the trigger to &lt;code&gt;OWNER&lt;/code&gt;, &lt;code&gt;MEMBER&lt;/code&gt;, or &lt;code&gt;COLLABORATOR&lt;/code&gt;, we ensure only trusted team members can summon the AI.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;So, when you need a quick review: just leave the comment, and watch the magic happen!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdz842msui87ykv2ow1ck.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdz842msui87ykv2ow1ck.png" alt="Triggering with /gemini-review" width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Using Out-of-the-Box Personalities
&lt;/h2&gt;

&lt;p&gt;You can configure the personality of your reviewer! A number of personas area available to choose from.&lt;/p&gt;

&lt;p&gt;Here's what a review from palpatine looks like:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F01sagu8a1jymh60gvtdq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F01sagu8a1jymh60gvtdq.png" alt="Palpatine Review" width="800" height="432"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And here's a review from Rick. Wubba-Lub-a-Dub-Dub!!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flz3ekzanf4ke8lf9zsiv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flz3ekzanf4ke8lf9zsiv.png" alt="Rick Review" width="800" height="573"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Wait, What About Issues Triage?
&lt;/h2&gt;

&lt;p&gt;I nearly forgot! My action can also be used to triage any issues that are raised against your repo.&lt;/p&gt;

&lt;p&gt;As your open-source projects grow, the issue tracker can quickly turn into a chaotic mess of bug reports, feature requests, spam, and questions. Keeping the backlog clean and correctly tagged is a chore that most developers dread.&lt;/p&gt;

&lt;p&gt;To help solve this, you can run my action in triage mode. When a new issue is opened, Gemini reviews the title and description, compares it against your existing repository labels, and automatically applies the most appropriate tags.&lt;/p&gt;

&lt;p&gt;What you get is an immediately organised issue backlog, complete with a brief reasoning comment explaining why the labels were selected. It takes the manual effort out of issue classification entirely.&lt;/p&gt;

&lt;p&gt;If you want to set this up in your repository, visit the &lt;a href="https://github.com/derailed-dash/gemini-review-action" rel="noopener noreferrer"&gt;repository&lt;/a&gt; for the full setup instructions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping-Up
&lt;/h2&gt;

&lt;p&gt;Sunsets are always frustrating, especially when they disrupt a workflow you’ve grown to rely on. But they also present a fantastic opportunity. An opportunity to learn and an opportunity to do things in a slightly different way. The main benefit for me is having a reviewer that’s now much faster than my old one. It consumes fewer runner minutes, it supports custom TOML prompts, and it leverages the latest from Gemini.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;PLEASE give the repository a star&lt;/strong&gt; , try the action out on your open-source projects, and let’s keep our CI/CD pipelines smart, secure, and fast!&lt;/p&gt;

&lt;p&gt;Let know how you get on!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;If you run into any issues or want to contribute a custom workflow, drop a comment, open an issue, or add your own contribution to &lt;a href="https://github.com/derailed-dash/gemini-review-action" rel="noopener noreferrer"&gt;derailed-dash/gemini-review-action&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Before You Go
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Please share&lt;/strong&gt; this with anyone that you think will be interested. It might help them, and it really helps me!&lt;/li&gt;
&lt;li&gt;Please &lt;strong&gt;give me loads of claps&lt;/strong&gt;! (Just hold down the clap button.)&lt;/li&gt;
&lt;li&gt;Please &lt;strong&gt;leave a comment&lt;/strong&gt; 💬. Interaction is good!&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Add a star&lt;/strong&gt; on the repo!&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Follow&lt;/strong&gt; and &lt;strong&gt;subscribe,&lt;/strong&gt; so you don’t miss my content.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Useful Links and References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dazbo.co.uk/" rel="noopener noreferrer"&gt;Dazbo’s Portfolio&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/derailed-dash/gemini-review-action" rel="noopener noreferrer"&gt;Dazbo’s Gemini PR Review &amp;amp; Triage Action (GitHub Repo)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/marketplace/actions/dazbo-s-gemini-code-review-issue-triage" rel="noopener noreferrer"&gt;Dazbo’s Gemini PR Review &amp;amp; Triage Action (GitHub Marketplace)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/derailed-dash/dazbo-agent-skills" rel="noopener noreferrer"&gt;Dazbo-Agent-Skills&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/google-github-actions/run-gemini-cli" rel="noopener noreferrer"&gt;Run-Gemini-CLI (Gemini CLI GitHub Actions)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developers.googleblog.com/an-important-update-transitioning-gemini-cli-to-antigravity-cli/?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;Gemini CLI Sunset and Migration Notice&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.cloud.google.com/gemini/docs/code-review/set-up-code-assist-github?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;Gemini Code Assist on GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developers.googleblog.com/gemini-code-assist/docs/deprecations/consumer-code-review?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;Gemini Code Assist Sunset Notice&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>githubactions</category>
      <category>pullrequest</category>
      <category>cicdpipeline</category>
      <category>googlegemini</category>
    </item>
    <item>
      <title>Building an Agentic FinOps Platform — Development Environment Setup, Google Antigravity, MCPs and Skills, and ADK Bootstrapping with Agents CLI</title>
      <dc:creator>Darren "Dazbo" Lester</dc:creator>
      <pubDate>Mon, 13 Jul 2026 15:31:20 +0000</pubDate>
      <link>https://dev.to/gde/building-an-agentic-finops-platform-development-environment-setup-google-antigravity-mcps-and-4c43</link>
      <guid>https://dev.to/gde/building-an-agentic-finops-platform-development-environment-setup-google-antigravity-mcps-and-4c43</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fj6st9qzdipor9ezy6ama.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fj6st9qzdipor9ezy6ama.gif" alt="Boostrapping with Agents-CLI and Skills" width="600" height="338"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TL;DR — This article is going to be jam-packed with useful information, tips, tricks and hacks for setting up an agentic development in the Google ecosystem.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This one isn’t really about the FinOps!&lt;/p&gt;

&lt;h2&gt;
  
  
  Welcome to Part 2
&lt;/h2&gt;

&lt;p&gt;Welcome back, friends!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F46lbn528ktckl4sspjsl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F46lbn528ktckl4sspjsl.png" alt="Dr Evil — Welcome Back!" width="498" height="287"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the &lt;a href="https://dev.to/google-cloud/finsavant-part-1-building-an-agentic-finops-platform-with-google-adk-a2ui-and-gemini-enterprise-248f59cea3a0"&gt;first part&lt;/a&gt;, I described the purpose of the &lt;a href="https://github.com/derailed-dash/smart-gcp-finops" rel="noopener noreferrer"&gt;FinSavant&lt;/a&gt; FinOps solution, the motivation for creating it, its overall architecture and tech stack, and how it works.&lt;/p&gt;

&lt;p&gt;In this part, we’ll use &lt;em&gt;FinSavant&lt;/em&gt; as a case study in &lt;strong&gt;how to set up a development environment&lt;/strong&gt; for the purposes of building such an ADK-based agentic solution. &lt;strong&gt;Even if you’re not particularly interested in &lt;em&gt;FinSavant&lt;/em&gt; itself, I hope you’ll find a bunch of useful information and tips here that will help you build your own agentic solutions more effectively and quickly.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We’ll cover:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Using Antigravity IDE&lt;/li&gt;
&lt;li&gt; Overall project workspace structure&lt;/li&gt;
&lt;li&gt; Setting up agent skills for your coding agent&lt;/li&gt;
&lt;li&gt; My project’s &lt;code&gt;GEMINI.md&lt;/code&gt; (or if you prefer, &lt;code&gt;AGENTS.md&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt; My documentation approach&lt;/li&gt;
&lt;li&gt; Setting up MCP servers for your coding agent, such as BigQuery MCP&lt;/li&gt;
&lt;li&gt; Scaffolding the initial ADK agent using Google Agents CLI and its supporting skill&lt;/li&gt;
&lt;li&gt; Getting started with a &lt;code&gt;Makefile&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Sound good? Let’s get cracking!&lt;/p&gt;

&lt;h2&gt;
  
  
  Series Orientation
&lt;/h2&gt;

&lt;p&gt;Let’s see where we are in this series.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;a href="https://dev.to/gde/finsavant-part-1-building-an-agentic-finops-platform-with-google-adk-a2ui-and-gemini-enterprise-29l3"&gt;Goals, Architecture, and Tech Stack: Capabilities, project goals, target architecture, technology stack, and design decisions.&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt; Development Environment Setup, Google Antigravity, MCPs and Skills, and ADK Bootstrapping with Agents CLI &lt;strong&gt;📍 You are here.&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt; Building the ADK Agent and API&lt;/li&gt;
&lt;li&gt; Designing and Building the UI with Google Stitch and A2UI&lt;/li&gt;
&lt;li&gt; Deployment with Gemini Enterprise Agent Platform, Agent Runtime, Cloud Run and IAP&lt;/li&gt;
&lt;li&gt; Automating Deployment with CI/CD and Terraform&lt;/li&gt;
&lt;li&gt; Agent Observability, Evaluation, and Tuning with Gemini Enterprise Agent Platform&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Getting Started with Antigravity IDE
&lt;/h2&gt;

&lt;p&gt;These days, my favourite coding environment &lt;em&gt;for any significant project&lt;/em&gt; is Antigravity IDE. This is Google’s &lt;em&gt;agent-first&lt;/em&gt; integrated development environment. You get a look-and-feel that’s familiar to VS Code users, but powered with autonomous, context-aware agents that can plan, execute, verify, and work in parallel.&lt;/p&gt;

&lt;p&gt;You can get it &lt;a href="https://antigravity.google/product/antigravity-ide?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;By the way, Antigravity IDE is just one member of the Antigravity (aka Agy) suite.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fq8lmru48uhh4sc2x3zf0.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fq8lmru48uhh4sc2x3zf0.jpeg" alt="Google Antigravity Suite" width="700" height="325"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I’ve covered these before, but here’s a quick reminder of the four Agy solutions in the suite:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Antigravity 2.0&lt;/strong&gt;, which is now the dedicated agent-first “builder” environment on your desktop. Notably, it doesn’t itself include an IDE. Instead, we now interact only with the agent manager. This surface aims to usher in the era of “idea to product” using agents, without concerning ourselves over the code. Many builders who don’t come from a coding background will love this.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Antigravity IDE&lt;/strong&gt;, which gives us the more familiar VS Code-esque coding environment, supported by the Antigravity agent harness. Here we can do agent-assisted development, and we always see the code. Coders will feel at home here.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Antigravity SDK&lt;/strong&gt;, which gives you the harness and tools that power Antigravity, but exposed as a Python Agent SDK. By importing from &lt;code&gt;google.antigravity&lt;/code&gt; we can programmatically leverage Antigravity’s capabilities.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Antigravity CLI&lt;/strong&gt;, which is the next evolution of the extremely awesome Gemini CLI. It’s still a terminal-first environment for interacting with Gemini models. But the new Antigravity CLI is built in Go, and you can tell; it feels much faster than Gemini CLI, both during startup and in general use. It leverages the same agent “harness” as Antigravity 2.0 and the IDE, and this allows for common settings and configuration across the Antigravity suite.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Project Structure
&lt;/h2&gt;

&lt;p&gt;Here’s the rough outline of the project structure we’ll be creating. We won’t be building all of this structure here; nor does this represent the final state of the project. But it gives you an idea of where we’re heading. (I’ll explain the &lt;code&gt;*&lt;/code&gt; in a minute!)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  smart-gcp-finops/  
  ├── agent/                # ADK agent package  
  │   ├── finops_agent/     # Root agent  
  │   ├── .env              # Agent specific environment vars  
  │   ├── Dockerfile        # For deploying agent to Agent Runtime  
  │   └── pyproject.toml    # Agent runtime dependencies  
* ├── bff/                # Backend-for-Frontend (API)  
* ├── deployment/         # Infrastructure &amp;amp; CI/CD (Terraform IaC)  
* │   ├── terraform/      # Centralised IaC for Prod &amp;amp; Staging  
  │   └── README.md         # Deployment documentation  
* ├── docs/               # Project documentation  
* │   ├── images/         # Diagrams and architectural visual assets  
  │   ├── DESIGN.md         # Visual identity, components, and UI design  
  │   ├── architecture-and-walkthrough.md # Solution blueprints, ADRs, and component data flows  
  │   └── testing.md        # Testing strategy and verification instructions  
* ├── frontend/           # React UI frontend  
* ├── notebooks/          # Jupyter notebooks for prototyping and evaluation  
* ├── scripts/            # Environment setup and other utility scripts  
  │   └── setup-env.sh      # Configure local environment including Google auth / ADC  
* ├── tests/              # Unit and integration test suites  
* │   ├── eval/           # Agent evaluation  
* │   ├── unit/           # Unit tests  
* │   └── integration/    # Integration tests  
* ├── .agents/            # Workspace customizations root  
  │   └── mcp_config.json   # E.g. MCP servers  
* ├── .github/            # GitHub Actions workflows and CI/CD  
* ├── .env                # Root environment vars (dev setup, unified container, GitHub, etc)  
  ├── .envrc                # Automatically launch when entering this directory  
* ├── .gitignore          # Exclude from git  
* ├── Makefile            # Centralised developer convenience commands  
* ├── GEMINI.md           # Development agent context &amp;amp; guidelines  
* ├── LICENSE             # Standard open-source license file  
* ├── pyproject.toml      # Root project configuration / dependencies  
* ├── README.md           # Developer documentation homepage  
  └── TODO.md               # TODO list
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you wanted to build such a structure from scratch, here’s a cool thing to try…&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Create your new project folder, e.g. &lt;code&gt;my-cool-project&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt; Open that folder in Antigravity IDE.&lt;/li&gt;
&lt;li&gt; Supply this prompt to the Agy Agent:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/grill-me Using this folder tree as a template, 
create the required folder structure in this workspace for my new Python 
project. Only create folders and files that are marked as '*'. 
For required files, provide initial starter-for-10 content. 
&amp;lt;&amp;lt; paste the tree structure here &amp;gt;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Why &lt;code&gt;/grill-me&lt;/code&gt;? This is a built-in Agy command that causes the agent to ask questions to remove ambiguity. If you were to give the agent a slightly vague prompt without this prefix, then the agent might make some guesses about what you want. But with &lt;code&gt;/grill-me&lt;/code&gt;, the agent will still make educated guesses, but it will also ask you questions to clarify your intent.&lt;/p&gt;

&lt;p&gt;The prompt above is a good example of where this is useful. You’ll notice that my project tree has a &lt;code&gt;LICENSE.md&lt;/code&gt; file, which is a standard component to include in open-source projects. But my prompt doesn't specify which license to use. So when you use &lt;code&gt;/grill-me&lt;/code&gt;, the agent will offer sensible license choices based on your project and context, and ask you to confirm.&lt;/p&gt;

&lt;p&gt;This video demonstrates Agy scaffolding the entire project from scratch, in response to the prompt above:&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/DmnBHilRjOo" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Give it a go!&lt;/p&gt;

&lt;h2&gt;
  
  
  Skills for Your Coding Agent
&lt;/h2&gt;

&lt;p&gt;I like to describe skills as &lt;strong&gt;units of knowledge that agents load on-demand&lt;/strong&gt;, when they need to do a particular task. I’ve previously written articles on the subject of my favourite skills, where to find them, and how to install them. I recommend you check out &lt;a href="https://dev.to/google-cloud/dialling-our-agents-to-11-agent-skills-you-need-to-be-using-ccffa51e91df"&gt;this one&lt;/a&gt;. You might want to go ahead and install all of my favourites!&lt;/p&gt;

&lt;p&gt;But for now, let’s add a few skills that will definitely be useful for our current project. I recommend installing them globally, so they’ll be available to all of your development projects.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx skills add https://github.com/vercel-labs/skills &lt;span class="nt"&gt;-y&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; &lt;span class="nt"&gt;--skill&lt;/span&gt; find-skills  
npx skills add https://github.com/derailed-dash/dazbo-agent-skills &lt;span class="nt"&gt;-y&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt;  
npx skills add https://github.com/google/skills &lt;span class="nt"&gt;-y&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt;  
npx skills add https://github.com/google-gemini/gemini-skills/ &lt;span class="nt"&gt;-y&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt;  
npx skills add https://github.com/shubhamsaboo/awesome-llm-apps/awesome-agent-skills &lt;span class="nt"&gt;-y&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; &lt;span class="nt"&gt;--skill&lt;/span&gt; technical-writer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We’re also going to install the &lt;em&gt;Google Agents CLI&lt;/em&gt; and its associated skills, but we’ll get to that later.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;GEMINI.md&lt;/code&gt; - Context for Your Coding Agent
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;GEMINI.md&lt;/code&gt; file (or &lt;code&gt;AGENTS.md&lt;/code&gt; if you prefer) is how you define your project's rules and context. It's where you tell the Agy Agent:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  About your project’s goals&lt;/li&gt;
&lt;li&gt;  Rules and guidelines you want it to follow&lt;/li&gt;
&lt;li&gt;  References you want it to read&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When we create &lt;code&gt;GEMINI.md&lt;/code&gt; in the root of a project then the file is scoped only to &lt;em&gt;that project&lt;/em&gt;. (This project-specific context gets appended to any global &lt;code&gt;GEMINI.md&lt;/code&gt; you have defined.) When you launch any Antigravity tool from this workspace - such as Agy 2.0, Agy IDE, or Agy CLI - the Agent will automatically read this context.&lt;/p&gt;

&lt;p&gt;Let me show you what my &lt;code&gt;GEMINI.md&lt;/code&gt; looked like, when starting out with &lt;em&gt;FinSavant&lt;/em&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gh"&gt;# FinSavant - the Agentic FinOps Solution  &lt;/span&gt;

&lt;span class="gu"&gt;## Project Goals  &lt;/span&gt;

To create an agentic FinOps solution for GCP that:  
&lt;span class="p"&gt;-&lt;/span&gt; Uses ADK for agent orchestration.  
&lt;span class="p"&gt;-&lt;/span&gt; Is able to examine billing and cost data in BigQuery, based on billing   
  exports.  
&lt;span class="p"&gt;-&lt;/span&gt; Is able to understand Google Cloud infrastructure and services across   
  multiple Google projects associated with a billing account.  
&lt;span class="p"&gt;-&lt;/span&gt; Considers projects associated with a particular Google Cloud organisation,    
  associated with a billing account.  
&lt;span class="p"&gt;-&lt;/span&gt; Leverages Google Developer Knowledge API MCP for grounding:   
  Google APIs, Google Cloud infrastructure, Google Cloud best practices.  
&lt;span class="p"&gt;-&lt;/span&gt; Is able to detect cost anomalies and inefficiencies, and trends.  
&lt;span class="p"&gt;-&lt;/span&gt; Is able to understand all deployed infra and services, and historical   
  configuration changes, leveraging Google Cloud Asset Inventory  
&lt;span class="p"&gt;-&lt;/span&gt; Is able to invoke Google Cloud Assist for immediate logs investigation,   
  RCA and recommendations.  
&lt;span class="p"&gt;-&lt;/span&gt; Is able to combine all of the above to provide actionable insights and   
  recommendations to users.  
&lt;span class="p"&gt;-&lt;/span&gt; Provides a UI for users, which includes:  
&lt;span class="p"&gt;  -&lt;/span&gt; Dashboard of cost trends, billing data and anomalies  
&lt;span class="p"&gt;  -&lt;/span&gt; Cost forecasting  
&lt;span class="p"&gt;  -&lt;/span&gt; Cost analysis  
&lt;span class="p"&gt;  -&lt;/span&gt; Anomaly detection  
&lt;span class="p"&gt;  -&lt;/span&gt; Recommendations  
&lt;span class="p"&gt;  -&lt;/span&gt; Cost optimisation suggestions  
&lt;span class="p"&gt;  -&lt;/span&gt; A natural language chat interface  
&lt;span class="p"&gt;-&lt;/span&gt; The UI should be based on React. Use skills you have available to leverage   
  React best practices.  
&lt;span class="p"&gt;-&lt;/span&gt; Leverage Google Stitch to design the UI, and use the Stitch MCP server to   
  pull in the design, in order to convert to React.  
&lt;span class="p"&gt;-&lt;/span&gt; The UI is connected to the agent via FastAPI.  
&lt;span class="p"&gt;-&lt;/span&gt; The UI and API will be hosted in a single Cloud Run service. The service   
  will be secured using IAP, using direct Cloud Run integration - no   
  Load Balancer.  
&lt;span class="p"&gt;-&lt;/span&gt; The Agent will be deployed to Agent Runtime in Gemini Enterprise Agent   
  Platform.  

&lt;span class="gu"&gt;## Tool Use: Skills, Gemini Enterprise Agent Platform, Agent Runtime and ADK  &lt;/span&gt;

Be sure to use all &lt;span class="gs"&gt;**agents**&lt;/span&gt; skills, &lt;span class="gs"&gt;**Gemini Enterprise Agent Platform**&lt;/span&gt;   
skills, and &lt;span class="gs"&gt;**ADK**&lt;/span&gt; skills you have available for developing ADK agents and   
best practices, and use &lt;span class="gs"&gt;**adk-docs-mcp**&lt;/span&gt; for latest ADK documentation.   

You will have additional skills available to you, but always check if the   
following can help with a particular task.  

&lt;span class="gu"&gt;### ADK &amp;amp; agents-cli Lifecycle Skills  &lt;/span&gt;
&lt;span class="p"&gt;
-&lt;/span&gt; &lt;span class="sb"&gt;`google-agents-cli-workflow`&lt;/span&gt;: Entrypoint for building ADK agents (scaffold,   
build, evaluate, deploy, publish, observe).  
[skipping for brevity]  

&lt;span class="gu"&gt;### Gemini Enterprise Agent Platform APIs  &lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="sb"&gt;`gemini-api`&lt;/span&gt;: Gemini Enterprise Agent Platform, Google Cloud, and   
Agent Platform enterprise usage with the Google Gen AI SDK.  
[skipping for brevity]  

&lt;span class="gu"&gt;### Agent Platform Engine &amp;amp; Model Management  &lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="sb"&gt;`agent-platform-deploy`&lt;/span&gt;: Deploying models and tuned weights to Agent   
  Platform endpoints.  
[skipping for brevity]  

&lt;span class="gu"&gt;## Key Internal Documentation  &lt;/span&gt;
&lt;span class="p"&gt;
-&lt;/span&gt; README.md - Project README; the developer's front door  
&lt;span class="p"&gt;-&lt;/span&gt; TODO.md - High level plan for the project  
&lt;span class="p"&gt;-&lt;/span&gt; architecture-and-walkthrough.md - The main architecture, including design   
  decisions  
&lt;span class="p"&gt;-&lt;/span&gt; DESIGN.md - Where we will capture the UI design  
&lt;span class="p"&gt;-&lt;/span&gt; testing.md - Where we will document test strategy, summary of tests,   
  testing instructions, any manual testing processes  
&lt;span class="p"&gt;-&lt;/span&gt; docs/blog.md - A blog post document we will build along the way  
&lt;span class="p"&gt;-&lt;/span&gt; /deployment/README.md - Deployment and CI/CD documentation  

&lt;span class="gu"&gt;## Essential Reading  &lt;/span&gt;

You should read and leverage these resources for guidance and best practices,   
in addition to the skills and MCP servers you have available for knowledge.  

| Resource | Description and Relevance |  
| -------- | ------------------------- |  
| https://docs.cloud.google.com/bigquery/docs/use-bigquery-mcp?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco | Use the BigQuery MCP server |   
| https://adk.dev/integrations/bigquery/?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco | BigQuery tool for ADK |  
| https://docs.cloud.google.com/gemini-enterprise-agent-platform?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco | Gemini Enterprise Agent Platform Overview |  
| https://adk.dev/deploy/agent-runtime?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco | ADK with Agent Runtime |  
[skipping for brevity]  

&lt;span class="gu"&gt;## Other Notes  &lt;/span&gt;
&lt;span class="p"&gt;
-&lt;/span&gt; "Vertex AI" no longer exists as a product; the replacement is Gemini   
  Enterprise Agent Platform.  
&lt;span class="p"&gt;-&lt;/span&gt; "Vertex AI Agent Engine" is no more; the replacement is "Agent Runtime",   
  which is a part of the Gemini Enterprise Agent Platform.  
&lt;span class="p"&gt;-&lt;/span&gt; But APIs and Google internal resource names may still refer to legacy names,   
  e.g. &lt;span class="sb"&gt;`reasoningEngine`&lt;/span&gt; rather than Agent Runtime. Always use the new names   
  when creating documentation, but be mindful that we may need to use old   
  names in API calls and certain resource definitions.  

&lt;span class="gu"&gt;## Blog  &lt;/span&gt;

I want to build a multi-part blog series, which I'll post on Medium and Dev.to.  

&lt;span class="gu"&gt;### Documenting As We Go  &lt;/span&gt;

As we go, document steps taken, experience and findings in docs/blog.md.   
Later, I will build a Medium blog from this content. During this "as we go"   
phase, the blog.md does not need to be a collection of notes, code snippets, and observations. It should:  
&lt;span class="p"&gt;
-&lt;/span&gt; Include all the key steps we did, in the order we did them.  
[skipping for brevity]  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you’re following along and you’ve just created your context file, give Agy a restart now, so it picks this up.&lt;/p&gt;

&lt;h2&gt;
  
  
  Documentation Approach
&lt;/h2&gt;

&lt;p&gt;I’m a big fan of having a consistent set of high-quality, continuously maintained documentation. I even have my own agent skill — &lt;code&gt;maintaining-core-documentation&lt;/code&gt; - to automate much of this for me. Check out my previous blog on this subject: &lt;a href="https://dev.to/google-cloud/documentation-as-context-a-skill-to-automate-your-blueprints-for-the-agentic-era-2bec0cf041a3"&gt;Documentation as Context: A Skill to Automate Your Blueprints for the Agentic Era&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you previously ran the &lt;code&gt;npx skills add https://github.com/derailed-dash/dazbo-agent-skills -y -g&lt;/code&gt; command from above, then you already have this skill installed.&lt;/p&gt;

&lt;p&gt;With this in place, you could issue this prompt to bootstrap a set of documentation for a brand-new project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Use maintaining-core-documentation to bootstrap my project documentation.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check out this video to see the skill doing its magic!&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/fvT_GJ4LPhE" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;As you evolve your project, this skill will automatically maintain your documentation.&lt;/p&gt;

&lt;h2&gt;
  
  
  MCP Servers for Your Coding Agent
&lt;/h2&gt;

&lt;p&gt;I’ve previously written about &lt;a href="https://dev.to/google-cloud/dialling-our-agents-to-11-my-favourite-mcp-servers-9549c1442a5e"&gt;some of my favourite MCP servers&lt;/a&gt;. There are only a couple that we’ll need for this project:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;a href="https://docs.cloud.google.com/bigquery/docs/use-bigquery-mcp?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;Google BigQuery Remote MCP Server&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://adk.dev/tutorials/coding-with-ai/?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco#adk-docs-mcp-server" rel="noopener noreferrer"&gt;ADK Docs MCP&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Note that we won’t be using either of these in the &lt;em&gt;FinSavant&lt;/em&gt; agent itself. These are purely to help us during development.&lt;/p&gt;

&lt;p&gt;Let’s try out the BigQuery MCP server first. In your workspace’s &lt;code&gt;.agents/mcp_config.json&lt;/code&gt; file, we configure the &lt;strong&gt;Remote BigQuery MCP server&lt;/strong&gt; like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;  
  &lt;/span&gt;&lt;span class="nl"&gt;"mcpServers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;  
    &lt;/span&gt;&lt;span class="nl"&gt;"bigquery-mcp-server"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;  
      &lt;/span&gt;&lt;span class="nl"&gt;"serverUrl"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://bigquery.googleapis.com/mcp"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;  
      &lt;/span&gt;&lt;span class="nl"&gt;"authProviderType"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"google_credentials"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;  
      &lt;/span&gt;&lt;span class="nl"&gt;"oauth"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;  
        &lt;/span&gt;&lt;span class="nl"&gt;"scopes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;  
          &lt;/span&gt;&lt;span class="s2"&gt;"https://www.googleapis.com/auth/bigquery"&lt;/span&gt;&lt;span class="w"&gt;  
        &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;  
      &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;  
      &lt;/span&gt;&lt;span class="nl"&gt;"headers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;  
        &lt;/span&gt;&lt;span class="nl"&gt;"x-goog-user-project"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"your-gcp-billing-project"&lt;/span&gt;&lt;span class="w"&gt;  
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;  
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;  
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;  
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A few things to note about this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Billing project&lt;/strong&gt;: Replace &lt;code&gt;your-gcp-billing-project&lt;/code&gt; with the Google project where your billing data export lives.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fo7b4crvrdlpd4ef8qn9l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fo7b4crvrdlpd4ef8qn9l.png" alt="BigQuery MCP Configuration" width="700" height="303"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;BigQuery API&lt;/strong&gt;: Make sure the BigQuery API (&lt;code&gt;bigquery.googleapis.com&lt;/code&gt;) is enabled on that project.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Developer Identity Permissions&lt;/strong&gt;: Because the MCP server uses &lt;code&gt;google_credentials&lt;/code&gt; to authenticate, your local developer account (active in &lt;code&gt;gcloud auth&lt;/code&gt;) must be authorised on Google Cloud. You need the &lt;code&gt;roles/bigquery.dataViewer&lt;/code&gt; and &lt;code&gt;roles/bigquery.jobUser&lt;/code&gt; roles on the project hosting the billing dataset.&lt;/li&gt;
&lt;li&gt;  You also need the &lt;code&gt;roles/mcp.toolUser&lt;/code&gt; role, in order to use this managed MCP server to query the BigQuery database.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And now, when you open the workspace in Antigravity IDE, it will load this configuration automatically. Your coding agent will be able to query schemas, inspect tables, and try out SQL queries in order to assist you when you actually create the &lt;em&gt;FinSavant&lt;/em&gt; agent code.&lt;/p&gt;

&lt;p&gt;Let’s test it!&lt;/p&gt;

&lt;p&gt;First, I issue this prompt to the Agy agent:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;What billing tables do I have? Explain their key functions.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Feu1hy9rer1ya227wazpf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Feu1hy9rer1ya227wazpf.png" alt="What billing tables do I have?" width="700" height="571"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can see the agent immediately finds the MCP server and asks for permission to invoke its tools. After I grant permission, I get this response:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fsqp17qkpwtbsp1vno4fy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fsqp17qkpwtbsp1vno4fy.png" alt="BQ MCP response" width="629" height="771"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Nice! You can see how helpful this is going to be.&lt;/p&gt;

&lt;h2&gt;
  
  
  Scaffolding Your ADK Agent
&lt;/h2&gt;

&lt;p&gt;The easiest way to scaffold a new ADK agent is to make use of &lt;strong&gt;Google Agents CLI&lt;/strong&gt;. The Agents CLI is actually a bundle, containing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  The &lt;strong&gt;Agents CLI&lt;/strong&gt; itself — commands for scaffolding, evaluating, deploying, and observing AI agents on Google Cloud. The &lt;a href="https://github.com/google/agents-cli" rel="noopener noreferrer"&gt;GitHub repo&lt;/a&gt; describes the commands available:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwyy9tqvje0ncsab949yg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwyy9tqvje0ncsab949yg.png" alt="Agents-CLI commands" width="700" height="355"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  An associated set of &lt;strong&gt;agent skills&lt;/strong&gt; that turn your development agent into an expert in using Agents CLI.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fylr6ixtlvs7jyxg8dkn2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fylr6ixtlvs7jyxg8dkn2.png" alt="Agents-CLI skills" width="700" height="368"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You install the bundle using this one-time command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;uvx google-agents-cli setup
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you already have it installed, then you can upgrade like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;uv tool upgrade google-agents-cli
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(It’s worth doing this occasionally — this CLI is evolving quickly!)&lt;/p&gt;

&lt;p&gt;With this installed, we &lt;em&gt;could&lt;/em&gt; create our top level &lt;code&gt;agent&lt;/code&gt; folder that contains a root agent called &lt;code&gt;finops_agent&lt;/code&gt; by running this command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;agents-cli scaffold create agent &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--agent&lt;/span&gt; adk &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--prototype&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--agent-directory&lt;/span&gt; finops_agent
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Foukl5oi8onyaezg0dbeo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Foukl5oi8onyaezg0dbeo.png" alt="Running agents-cli scaffold create" width="615" height="414"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You’ll end up with the following inside of your workspace folder:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;agent/  
├── finops_agent/                 # Your agent code  
│   ├── __init__.py               # Registers the app (exports `app`)  
│   ├── agent.py                  # Agent definition — instructions, model, tools  
│   └── app_utils/                # Utilities (telemetry, converters)  
│       ├── __init__.py  
│       ├── telemetry.py          # OpenTelemetry setup for Cloud Trace  
│       ├── typing.py             # Request/response Pydantic models  
│       └── gcs.py                # GCS utility functions  
│  
├── tests/  
│   ├── eval/                     # Evaluation test cases  
│   │   ├── datasets/  
│   │   │   └── basic-dataset.json    # Default eval cases  
│   │   └── eval_config.yaml          # Evaluation metrics configuration  
│   ├── integration/  
│   │   └── test_agent.py         # Integration test (runs agent end-to-end)  
│   └── unit/  
│       └── test_dummy.py         # Placeholder for unit tests  
│  
├── .env                          # Environment variables (project ID, location)  
├── .env.example                  # Example environment variables  
├── .gitignore                    # Git ignore file  
├── pyproject.toml                # Project config and dependencies  
├── agents-cli-manifest.yaml      # Configuration for agents-cli  
├── Dockerfile                    # Dockerfile for the agent runtime  
└── GEMINI.md                     # Guidance file for coding agents
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But since we now have the skills installed, there’s an easier way to accomplish this, that doesn’t require you to check the CLI documentation…&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Please bootstrap a new ADK agent project. The agent top-level project should   
be named `agent`, and it should contain a root `agent-directory` called   
`finops_agent`, NOT the default of `app`. This means `pyproject.toml` and   
other config files will live under `agent/`, and all Python source files   
(like `agent.py` and `fast_api_app.py`) will live inside   
`agent/finops_agent/`.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sure, this prompt is quite detailed, but I’m after a very specific folder structure.&lt;/p&gt;

&lt;p&gt;Let’s see a live demo…&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/wxMK7MJwHqA" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;As you can see from the demo, we can now use &lt;code&gt;agents-cli&lt;/code&gt; to check if our newly scaffolded agent is working.&lt;/p&gt;

&lt;p&gt;For example, by issuing a single test prompt on the command line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;agent  
agents-cli run &lt;span class="s2"&gt;"Hello! Who are you?"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjj97qru6g5fku1iwxf2j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjj97qru6g5fku1iwxf2j.png" alt="agents-cli run" width="700" height="323"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Or, we could run up the extremely powerful and useful &lt;strong&gt;ADK Web&lt;/strong&gt; interface, using this handy shortcut:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# From the agent folder&lt;/span&gt;
agents-cli playground
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffdg0eav3679kw1v7nwpr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffdg0eav3679kw1v7nwpr.png" alt="agents-cli playground" width="800" height="529"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Concluding thought about &lt;code&gt;Agents-CLI&lt;/code&gt;: if you know your way around the CLI, you can use it directly. It'll be faster and use fewer tokens. But when you're doing lots of agent related activities like boostrapping, adding CI/CD, deploying and evaluating, you'll probably find that natural language conversations are going to save you a lot of time and pain.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bonus #1: Getting Started with a Makefile
&lt;/h2&gt;

&lt;p&gt;In a “monorepo” project setup like &lt;em&gt;FinSavant&lt;/em&gt;, you quickly end up managing a lot of moving parts: building frontend assets, compiling Python environments, building and running multiple Docker images, executing test suites, and deploying resources to various target environments.&lt;/p&gt;

&lt;p&gt;Rather than forcing yourself (or your team) to remember a massive list of commands and flags, wrapping them in a &lt;code&gt;Makefile&lt;/code&gt; is a big win.&lt;/p&gt;

&lt;p&gt;But what actually is a &lt;code&gt;Makefile&lt;/code&gt;? At its core, it is a configuration file used by the classic &lt;code&gt;make&lt;/code&gt; build automation tool. These days it has evolved into a lightweight, standardised task runner. It allows us to define short aliases (known as "targets") for complex shell commands, documenting project workflows in a single, standard file that is easy for both humans and agents to discover.&lt;/p&gt;

&lt;p&gt;Earlier, during the demonstration of bootstrapping the project, the agent actually created an initial &lt;code&gt;Makefile&lt;/code&gt; for us. If you followed along, you'll now have a &lt;code&gt;Makefile&lt;/code&gt; that looks something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="nl"&gt;.PHONY&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;install lint format lint-fix test  &lt;/span&gt;

&lt;span class="nl"&gt;install&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;  
    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nb"&gt;command&lt;/span&gt; &lt;span class="nt"&gt;-v&lt;/span&gt; uv &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;/dev/null 2&amp;gt;&amp;amp;1 &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"uv is not installed. Installing uv..."&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; curl &lt;span class="nt"&gt;-LsSf&lt;/span&gt; https://astral.sh/uv/0.11.16/install.sh | sh&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;source&lt;/span&gt; &lt;span class="nv"&gt;$HOME&lt;/span&gt;/.local/bin/env&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;  
    uv &lt;span class="nb"&gt;sync&lt;/span&gt;  

&lt;span class="nl"&gt;lint&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;  
    uvx codespell@latest &lt;span class="nt"&gt;-s&lt;/span&gt;  
    uvx ruff@latest check &lt;span class="nb"&gt;.&lt;/span&gt;  

&lt;span class="nl"&gt;lint-fix&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;  
    uvx codespell@latest &lt;span class="nt"&gt;-w&lt;/span&gt;  
    uvx ruff@latest check &lt;span class="nt"&gt;--fix&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt;  

&lt;span class="nl"&gt;test&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;  
    uv run pytest tests/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you can run any of these &lt;code&gt;make&lt;/code&gt; &lt;em&gt;targets&lt;/em&gt;, like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;make &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this in place, we can build on it in future articles as we develop the &lt;em&gt;FinSavant&lt;/em&gt; solution.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bonus #2: My Setup-Env Script
&lt;/h2&gt;

&lt;p&gt;These days, whenever I’m working on a project that makes use of Google services, I always create a helper &lt;code&gt;setup-env&lt;/code&gt; script to configure my environment for me.&lt;/p&gt;

&lt;p&gt;This script:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Loads environment variables&lt;/strong&gt;: Automatically exports all key/value pairs from &lt;code&gt;.env&lt;/code&gt; directly into the current shell session.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Handles Google Cloud authentication&lt;/strong&gt;: If not skipped (via the &lt;code&gt;--noauth&lt;/code&gt; flag), it runs &lt;code&gt;gcloud auth login --update-adc&lt;/code&gt; to authenticate the user and configure Google Application Default Credentials (ADC).&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Sets the active gcloud project&lt;/strong&gt;: Configures &lt;code&gt;gcloud&lt;/code&gt; defaults for the target project and billing quota project settings.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Extracts project metadata&lt;/strong&gt;: Dynamically retrieves the Google Cloud Project Number and constructs helper variables (like the Cloud Build service account email) for deployment scripts.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Synchronises Python dependencies&lt;/strong&gt;: Runs &lt;code&gt;uv sync&lt;/code&gt; to ensure all standard, development, and notebook dependencies are installed in the local environment.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Activates the virtual environment&lt;/strong&gt;: Activates the local Python virtual environment (&lt;code&gt;.venv&lt;/code&gt;) so the user is immediately ready to run code.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You can find a copy of this &lt;code&gt;scripts/setup-env.sh&lt;/code&gt; in my &lt;a href="https://github.com/derailed-dash/smart-gcp-finops/blob/main/scripts/setup-env.sh" rel="noopener noreferrer"&gt;GitHub repository&lt;/a&gt;. Because it uses standard environment variables defined in your &lt;code&gt;.env&lt;/code&gt;, you can use it in any of your Google projects!&lt;/p&gt;

&lt;p&gt;You run it from the project root directory like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;source &lt;/span&gt;scripts/setup-env.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Bonus #3: Automating Setup with &lt;code&gt;direnv&lt;/code&gt; and &lt;code&gt;.envrc&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;If you haven’t come across this before, I think you’re going to like it!&lt;/p&gt;

&lt;p&gt;Manually sourcing the &lt;code&gt;setup-env.sh&lt;/code&gt; script every time I open a terminal in the project directory is a bit of a chore. To automate this, we can use &lt;code&gt;direnv&lt;/code&gt; — an extension for your shell that automatically runs custom scripts and loads / unloads environment variables depending on your current directory.&lt;/p&gt;

&lt;p&gt;By placing a &lt;code&gt;.envrc&lt;/code&gt; file at the root of the project, &lt;code&gt;direnv&lt;/code&gt; automatically executes it whenever you &lt;code&gt;cd&lt;/code&gt; into the directory.&lt;/p&gt;

&lt;p&gt;Here is what our &lt;code&gt;.envrc&lt;/code&gt; looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s2"&gt;".venv"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then  
  &lt;/span&gt;uv venv  
&lt;span class="k"&gt;fi&lt;/span&gt;  

&lt;span class="c"&gt;# Check if gcloud token is still valid to avoid re-authenticating  &lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;gcloud auth print-access-token &lt;span class="nt"&gt;--quiet&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /dev/null 2&amp;gt;&amp;amp;1&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then  
  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"gcloud token is valid, skipping authentication."&lt;/span&gt;  
  &lt;span class="nb"&gt;source &lt;/span&gt;scripts/setup-env.sh &lt;span class="nt"&gt;--noauth&lt;/span&gt;  
&lt;span class="k"&gt;else  
  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"gcloud token is not valid, re-authenticating."&lt;/span&gt;  
  &lt;span class="nb"&gt;source &lt;/span&gt;scripts/setup-env.sh  
&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This configuration does a few smart things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Bootstraps the virtual environment&lt;/strong&gt;: Automatically initialises a virtual environment using &lt;code&gt;uv venv&lt;/code&gt; if it doesn't already exist.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Verifies active Google session&lt;/strong&gt;: Runs &lt;code&gt;gcloud auth print-access-token&lt;/code&gt; silently to check if our Google Cloud session is active.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Conditionally sources configuration&lt;/strong&gt;: If the Google Cloud session is still valid, it sources the setup-env script with the &lt;code&gt;--noauth&lt;/code&gt; flag, avoiding repetitive and annoying browser login prompts. If the session has expired, it triggers the full setup script to re-authenticate.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;There are a couple of one-off steps we have to do to get &lt;code&gt;direnv&lt;/code&gt; up and running:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Install &lt;code&gt;direnv&lt;/code&gt;. On Debian/Ubuntu systems, this is &lt;code&gt;sudo apt install direnv&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt; Allow &lt;em&gt;this&lt;/em&gt; folder for &lt;code&gt;direnv&lt;/code&gt;. Run &lt;code&gt;direnv allow&lt;/code&gt; in the terminal, in the project folder where we've placed our &lt;code&gt;.envrc&lt;/code&gt; file.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now, when we enter our project folder, the script runs automatically, like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8muwcqhjvvadijl55akm.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8muwcqhjvvadijl55akm.gif" alt="direnv demo" width="719" height="428"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Pretty neat, right?&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrap-Up and Next Steps
&lt;/h2&gt;

&lt;p&gt;Okay, we’re done with the environment setup. We’ve:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Setup Google Antigravity, along with some killer skills and MCP servers&lt;/li&gt;
&lt;li&gt;  Bootstrapped our project using the Agy agent&lt;/li&gt;
&lt;li&gt;  Played with &lt;code&gt;/grill-me&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  Established an initial set of core project documentation, using a custom skill&lt;/li&gt;
&lt;li&gt;  Used the Agy agent to bootstrap an ADK agent, making use of &lt;code&gt;agents-cli&lt;/code&gt; and its skills&lt;/li&gt;
&lt;li&gt;  Created a &lt;code&gt;Makefile&lt;/code&gt; for standardising common development, testing and deployment tasks&lt;/li&gt;
&lt;li&gt;  Created a &lt;code&gt;scripts/setup-env.sh&lt;/code&gt; script for setting up our Google Cloud environment&lt;/li&gt;
&lt;li&gt;  Used &lt;code&gt;direnv&lt;/code&gt; and a &lt;code&gt;.envrc&lt;/code&gt; file to automate the setup process, every time we open a terminal in this directory&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the next part, we’ll look at the actual code for our &lt;em&gt;FinSavant&lt;/em&gt; agents and tools!&lt;/p&gt;

&lt;p&gt;See you there!&lt;/p&gt;

&lt;h2&gt;
  
  
  Before You Go
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Please share&lt;/strong&gt; this with anyone that you think will be interested. It might help them, and it really helps me!&lt;/li&gt;
&lt;li&gt;  Please &lt;strong&gt;give me loads of claps&lt;/strong&gt;! (Just hold down the clap button.)&lt;/li&gt;
&lt;li&gt;  Please &lt;strong&gt;leave a comment&lt;/strong&gt; 💬. Interaction is good!&lt;/li&gt;
&lt;li&gt;  and &lt;strong&gt;subscribe,&lt;/strong&gt; so you don’t miss my content.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Useful Links and References
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Project Demo &amp;amp; Portfolio
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;a href="https://github.com/derailed-dash/smart-gcp-finops" rel="noopener noreferrer"&gt;FinSavant on GitHub&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://dazbo.co.uk" rel="noopener noreferrer"&gt;Dazbo’s Portfolio&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Gemini Enterprise Agent Platform &amp;amp; ADK
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;a href="https://docs.cloud.google.com/gemini-enterprise-agent-platform/overview?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;Gemini Enterprise Agent Platform Overview&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://docs.cloud.google.com/gemini-enterprise-agent-platform/build/adk?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;ADK Agent Building Guide&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://github.com/google/agents-cli?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;Agents CLI on GitHub&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://google.github.io/agents-cli/?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;Agents CLI Documentation&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Google Cloud Services &amp;amp; APIs
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;a href="https://docs.cloud.google.com/cloud-assist/overview?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;Google Cloud Assist&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://docs.cloud.google.com/asset-inventory/docs/overview?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;Cloud Asset Inventory (CAI) API&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://developers.google.com/knowledge/mcp?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;Developer Knowledge MCP Server&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Other Related Articles &amp;amp; Resources
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;a href="https://antigravity.google/product/antigravity-ide?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;Antigravity IDE Documentation&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://makefiletutorial.com/" rel="noopener noreferrer"&gt;Makefile Tutorial&lt;/a&gt; — A modern, visual guide to writing GNU Makefiles.&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://astral.sh/uv" rel="noopener noreferrer"&gt;uv Package Manager&lt;/a&gt; — Fast Python package manager and resolver.&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://docs.astral.sh/ruff/" rel="noopener noreferrer"&gt;Ruff Linter &amp;amp; Formatter&lt;/a&gt; — Blazing fast linter and formatter for Python.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>finops</category>
      <category>antigravity</category>
      <category>agentscli</category>
      <category>adk</category>
    </item>
    <item>
      <title>FinSavant Part 1: Building an Agentic FinOps Platform with Google ADK, A2UI and Gemini Enterprise Agent Platform — Goals, Architecture, and Tech Stack</title>
      <dc:creator>Darren "Dazbo" Lester</dc:creator>
      <pubDate>Wed, 01 Jul 2026 04:25:12 +0000</pubDate>
      <link>https://dev.to/gde/finsavant-part-1-building-an-agentic-finops-platform-with-google-adk-a2ui-and-gemini-enterprise-29l3</link>
      <guid>https://dev.to/gde/finsavant-part-1-building-an-agentic-finops-platform-with-google-adk-a2ui-and-gemini-enterprise-29l3</guid>
      <description>&lt;h2&gt;
  
  
  Welcome
&lt;/h2&gt;

&lt;p&gt;Hello folks, Dazbo here. I’m on holiday, which means I’ve got time to catch-up on some blogging of my recent experiments!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fs82f2r69ki3erdrzphyj.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fs82f2r69ki3erdrzphyj.jpeg" alt="Blogging on holiday" width="800" height="609"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you’ve ever had to manage a Google Cloud Platform footprint of any decent size, you’ll know the feeling. You open up the billing console, look at the monthly total, and feel your eyes water. You start digging into dashboards, trying to map raw costs to actual running infrastructure, and quickly realise you’re essentially flying blind.&lt;/p&gt;

&lt;p&gt;To be fair, Google has made a bunch of improvements lately, with its own &lt;a href="https://docs.cloud.google.com/billing/docs/how-to/finops-hub?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;Google Cloud FinOps Hub&lt;/a&gt;. As Google describes it:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;“The FinOps hub presents all of your active savings and optimization opportunities in one dashboard.”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;But I wanted to build my own agentic FinOps solution, for a few reasons. Some are about the FinOps capability itself:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I want to be able to have &lt;strong&gt;natural language conversations with the agent&lt;/strong&gt;. I want to be able to dig into my cost spikes, and ask follow-up questions.&lt;/li&gt;
&lt;li&gt;I want an agentic solution that can combine information like &lt;strong&gt;&lt;em&gt;what&lt;/em&gt; I spent last month, &lt;em&gt;why&lt;/em&gt; I spent it, and why &lt;em&gt;spending spikes&lt;/em&gt; occurred&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;I want the solution to be able to immediately &lt;strong&gt;spot &lt;em&gt;orphaned resources&lt;/em&gt;&lt;/strong&gt; , such as unused VMs, unattached disks, or unused IP addresses. For example, a persistent disk costing us $100 a month might be adding value if it’s actually attached to a VM; but it’s a total waste of spend if it’s not. (Obviously, this is more of a problem for traditional IaaS infrastructure; this is not generally a concern for serverless services.)&lt;/li&gt;
&lt;li&gt;I want &lt;strong&gt;the solution to understand Google Cloud &lt;em&gt;architecture&lt;/em&gt; and &lt;em&gt;best practices&lt;/em&gt;&lt;/strong&gt; , so that it can advise &lt;em&gt;what I should do&lt;/em&gt;, and &lt;em&gt;why this is the most appropriate course of action&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But mainly, I wanted an excuse to experiment with some relatively new agentic services in Google Cloud:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I wanted to deploy to the new &lt;strong&gt;Gemini Enterprise&lt;/strong&gt; &lt;a href="https://docs.cloud.google.com/gemini-enterprise-agent-platform/build/runtime?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;&lt;strong&gt;Agent Runtime&lt;/strong&gt;&lt;/a&gt;; the thing that has replaced Vertex AI Agent Engine.&lt;/li&gt;
&lt;li&gt;I wanted to play with some of the associated &lt;a href="https://docs.cloud.google.com/gemini-enterprise-agent-platform/overview?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;&lt;strong&gt;Gemini Enterprise Agent Platform&lt;/strong&gt;&lt;/a&gt; capabilities, such as native support for &lt;a href="https://docs.cloud.google.com/gemini-enterprise-agent-platform/build/adk?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;&lt;strong&gt;ADK agents&lt;/strong&gt;&lt;/a&gt;, the &lt;a href="https://docs.cloud.google.com/gemini-enterprise-agent-platform/govern/agent-registry?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;&lt;strong&gt;Agent Registry&lt;/strong&gt;&lt;/a&gt; &lt;strong&gt;,&lt;/strong&gt; and built-in &lt;a href="https://docs.cloud.google.com/gemini-enterprise-agent-platform/optimize/observability/overview?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;&lt;strong&gt;observabiltiy and telemetry&lt;/strong&gt;&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;I wanted to experiment with some specific &lt;strong&gt;tools and MCP servers&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Specifically:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Native &lt;a href="https://adk.dev/integrations/bigquery/?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;BigQuery tools from ADK&lt;/a&gt; — in order to interrogate billing information in BigQuery.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.cloud.google.com/cloud-assist/overview?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;Google Cloud Assist&lt;/a&gt; — to be able to obtain live insights from Google Cloud metrics and logging, and provide recommendations using Google built-in recommenders.&lt;/li&gt;
&lt;li&gt;The &lt;a href="https://docs.cloud.google.com/asset-inventory/docs/overview?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;Asset Inventory API&lt;/a&gt; — to determine our exact current deployment configuration, to identify orphaned resources, and to see what has changed.&lt;/li&gt;
&lt;li&gt;The &lt;a href="https://developers.google.com/knowledge/mcp?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;Developer Knowledge MCP&lt;/a&gt; — so that my agent always has the latest knowledge about Google products, services, APIs, architectures, and best practices.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And so, friends, I give you &lt;strong&gt;FinSavant&lt;/strong&gt; , an agentic FinOps solution for GCP that gives you an active, infrastructure-aware virtual analyst that combines costs with real-time operational context, and can make recommendations about what you should do next.&lt;/p&gt;

&lt;p&gt;This is what it looks like:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6rgnzigyih71h9ri5tth.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6rgnzigyih71h9ri5tth.png" alt="FinSavant — React UI with A2UI" width="800" height="410"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I’ve open sourced the project, and you can find the &lt;a href="https://github.com/derailed-dash/smart-gcp-finops" rel="noopener noreferrer"&gt;project and its code on GitHub&lt;/a&gt;. If you like it or think it's useful, please add a star to the GitHub repo.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/derailed-dash/smart-gcp-finops" rel="noopener noreferrer"&gt;GitHub - derailed-dash/smart-gcp-finops&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Series Structure
&lt;/h2&gt;

&lt;p&gt;Let’s see where we are in this series.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Goals, Architecture, and Tech Stack: Capabilities, project goals, target architecture, technology stack, and design decisions. &lt;strong&gt;📍 You are here.&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Dev Environment Setup with Google Antigravity, ADK, Agents CLI, MCP &amp;amp; Skills&lt;/li&gt;
&lt;li&gt;Building the ADK Agent and API&lt;/li&gt;
&lt;li&gt;Designing and Building the UI with Google Stitch and A2UI&lt;/li&gt;
&lt;li&gt;Deployment with Gemini Enterprise Agent Platform, Agent Runtime, Cloud Run and IAP&lt;/li&gt;
&lt;li&gt;Automating Deployment with CI/CD and Terraform&lt;/li&gt;
&lt;li&gt;Agent Observability, Evaluation, and Tuning with Gemini Enterprise Agent Platform&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  FinSavant: How Does It Work?
&lt;/h2&gt;

&lt;p&gt;FinSavant is a conversational agent that uses:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://docs.cloud.google.com/billing/docs/how-to/export-data-bigquery?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;&lt;strong&gt;BigQuery Billing Exports&lt;/strong&gt;&lt;/a&gt; to know exactly what our costs are, down to the resource ID. Of course, this means you need to be exporting you billing data to BigQuery in the first place. Setting up &lt;a href="https://docs.cloud.google.com/billing/docs/how-to/export-data-bigquery?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;billing exports to BigQuery&lt;/a&gt; is a standard process.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.cloud.google.com/cloud-assist/overview?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;&lt;strong&gt;Google Cloud Assist&lt;/strong&gt;&lt;/a&gt; in order to interrogate our services, metrics and logs, and provide recommendations accordingly.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.cloud.google.com/asset-inventory/docs/overview?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;&lt;strong&gt;Google Cloud Asset Inventory&lt;/strong&gt;&lt;/a&gt; to understand our real-time deployment configuration, but also to provide a 35-day audit history of every asset change in our GCP estate. We can use this to investigate any changes that may have driven a cost spike.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developers.google.com/knowledge/mcp?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;&lt;strong&gt;Developer Knowledge MCP&lt;/strong&gt;&lt;/a&gt; to ground the agent with both broad and deep Google knowledge. This means that if you ask it any questions relating to Google Cloud, Google APIs, or general Google best practices, the agent will provide factually correct answers that are up-to-date, and with very little hallucination. For example, if a Cloud Run service seems costly, we can ask the agent for best practices on what we should do to reduce costs whilst, for example, maintaining availability.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By bringing these together under a GenAI agent built with the Google Agent Development Kit (ADK), we have created an assistant that can perform root-cause analysis on cost spikes, as well as provide recommendations on how to fix them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Architecture Overview
&lt;/h2&gt;

&lt;p&gt;When designing FinSavant, I wanted a clean separation between the frontend delivery mechanism and the agentic backend, while keeping deployment costs and security overhead to an absolute minimum.&lt;/p&gt;

&lt;p&gt;The overall architecture looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqwn573lyqx5ub3c1owvw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqwn573lyqx5ub3c1owvw.png" alt="FinSavant Component Architecture" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Tech Stack &amp;amp; Design Decisions
&lt;/h2&gt;

&lt;p&gt;Let’s dive into the core components that make up FinSavant’s tech stack and see how they complement one another.&lt;/p&gt;

&lt;h3&gt;
  
  
  User Interface: React/Vite
&lt;/h3&gt;

&lt;p&gt;With React I can create a great looking UI, and I have the ability to render dynamic A2UI widgets. (More on this in a future part of the series.)&lt;/p&gt;

&lt;p&gt;&lt;em&gt;By the way: I’m no frontend developer. I used Stitch to help me design and prototype the frontend UI, and then I used Antigravity (Gemini) to turn this into React code.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I can compile the React UI to clean, static assets, so I don’t need Node.js. This means my frontend container image will be pretty small, and therefore fast and cheap to run.&lt;/p&gt;

&lt;h3&gt;
  
  
  Rich UI with Agent-to-UI (A2UI)
&lt;/h3&gt;

&lt;p&gt;Rather than building a static dashboard or a free-form chatbot, FinSavant uses &lt;strong&gt;Agent-to-UI (A2UI)&lt;/strong&gt; to dynamically render rich UI components like tables, charts, and summary cards directly from the LLM. This ensures the interface is always context-aware and adapts to the user’s specific query.&lt;/p&gt;

&lt;p&gt;A2UI is Google’s declarative specification that enables agents to generate dynamic user interfaces in the form of JSON objects. So for FinSavant, the agent builds the UI component on-the-fly, and then our frontend just converts this JSON object into a React component and renders it.&lt;/p&gt;

&lt;p&gt;This is a game-changer for building a UI. I don’t have to hard-code any UI components — the agent decides what to display in real time! I’ll show you exactly how to do this in a future part of the series.&lt;/p&gt;

&lt;h3&gt;
  
  
  Backend-for-Frontend (BFF)
&lt;/h3&gt;

&lt;p&gt;The FastAPI BFF simply acts as a secure proxy. It streams queries to the agent and receives structured responses. But also, it allows us to decouple the backend from the UI. If I want surface this application through a different UI in the future — like &lt;a href="https://docs.cloud.google.com/gemini/enterprise/docs" rel="noopener noreferrer"&gt;Gemini Enterprise&lt;/a&gt; — I can.&lt;/p&gt;

&lt;h3&gt;
  
  
  UI &amp;amp; BFF Unified Container
&lt;/h3&gt;

&lt;p&gt;I’ve packaged the React frontend and FastAPI BFF into a single container image. This eliminates cross-origin resource sharing (CORS) headaches, minimises the runtime footprint, and simplifies the deployment.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cloud Run for Container Hosting
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://docs.cloud.google.com/run/docs/overview/what-is-cloud-run?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;Cloud Run&lt;/a&gt; is Google’s serverless, zero-ops, autoscaling container hosting environment. This is perfect for hosting our UI/BFF container. There are a number of useful features I’m going to make use of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It scales to 0, so it doesn’t cost anything when there’s no traffic.&lt;/li&gt;
&lt;li&gt;It autoscales based on demand, but we can limit the number of instances in order to control costs.&lt;/li&gt;
&lt;li&gt;It natively integrates with Google Identity-Aware Proxy, providing a simple way to ensure only authenticated / authorised users can get to our application. (This native integration, without need for a load balancer, is a fairly new feature.)&lt;/li&gt;
&lt;li&gt;We can map a domain name to our Cloud Run service, without need for a separate load balancer. (This is quite a new feature.)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Authentication with Identity-Aware Proxy
&lt;/h3&gt;

&lt;p&gt;I’ve secured the Cloud Run service using Google’s &lt;a href="https://docs.cloud.google.com/iap/docs/concepts-overview?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;Identity-Aware Proxy (IAP)&lt;/a&gt;. This is a cool service that both authenticates and authorises users before they can access our Cloud Run service. Unauthorised users will not be able to see the application.&lt;/p&gt;

&lt;p&gt;Until recently, the only way to use IAP with Cloud Run was to put a load balancer in front of the Cloud Run service and associate IAP with the LB. This adds additional complexity and cost.&lt;/p&gt;

&lt;p&gt;But now we can secure a Cloud Run service directly with IAP, without needing the LB. I’ve &lt;a href="https://medium.com/google-cloud/using-google-identity-aware-proxy-iap-with-cloud-run-without-a-load-balancer-27db89b9ed49?sharedUserId=derailed.dash" rel="noopener noreferrer"&gt;blogged about this before&lt;/a&gt;, when the feature first went into &lt;em&gt;Preview&lt;/em&gt;. But now it’s &lt;a href="https://cloud.google.com/blog/products/serverless/iap-integration-with-cloud-run?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;&lt;em&gt;Generally Available&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fagayman33vaqoi52dka5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fagayman33vaqoi52dka5.png" alt="Identity-Aware Proxy with Cloud Run" width="700" height="222"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Agent Orchestration: Google Agent Development Kit (ADK)
&lt;/h3&gt;

&lt;p&gt;ADK is an open source framework and SDK for building agents and agentic systems. These days I reach for it automatically.&lt;/p&gt;

&lt;p&gt;This is what it gives us:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Powerful multi-agent orchestration.&lt;/li&gt;
&lt;li&gt;Session context management.&lt;/li&gt;
&lt;li&gt;Bi-directional streaming support.&lt;/li&gt;
&lt;li&gt;Agnostic of AI model.&lt;/li&gt;
&lt;li&gt;Agnostic of hosting environment, but optimised for hosting on the Google Agent Runtime.&lt;/li&gt;
&lt;li&gt;Integrates natively with Gemini Enterprise Agent Platform / Agent Runtime.&lt;/li&gt;
&lt;li&gt;Easy to configure telemetry and observability.&lt;/li&gt;
&lt;li&gt;Really useful local development user interfaces.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Agent Runtime for ADK Agent Hosting
&lt;/h3&gt;

&lt;p&gt;Having decided I wanted to deploy the agent independently of the frontend and FastAPI, the next question is: where should we deploy the agent itself?&lt;/p&gt;

&lt;p&gt;In days gone by I would probably have deployed it to a separate Cloud Run service. But now we have &lt;a href="https://docs.cloud.google.com/gemini-enterprise-agent-platform/build/runtime" rel="noopener noreferrer"&gt;Agent Runtime&lt;/a&gt;, Google’s evolution of their previous product, Agent Engine. It is built for hosting agents and has a number of benefits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It is simple to deploy ADK agents to Agent Runtime, using the &lt;a href="https://google.github.io/agents-cli/?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;Agents CLI&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;It is serverless and autoscaling.&lt;/li&gt;
&lt;li&gt;When there’s no demand for the agent, there’s no cost.&lt;/li&gt;
&lt;li&gt;Exposing the agent’s endpoint to consumers (like our BFF in Cloud Run) is trivial.&lt;/li&gt;
&lt;li&gt;Agents deployed to Agent Runtime are automatically registered in the Gemini Enterprise Agent Platform’s &lt;a href="https://docs.cloud.google.com/agent-registry/overview?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;Agent Registry&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Agents deployed to Agent Runtime can leverage the various capabilities of &lt;a href="https://docs.cloud.google.com/gemini-enterprise-agent-platform/overview?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;GEAP&lt;/a&gt;, like &lt;a href="https://docs.cloud.google.com/gemini-enterprise-agent-platform/scale/memory-bank?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;Memory Bank&lt;/a&gt;, &lt;a href="https://docs.cloud.google.com/gemini-enterprise-agent-platform/govern/gateways/agent-gateway-overview?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;Agent Gateway&lt;/a&gt;, &lt;a href="https://docs.cloud.google.com/model-armor/overview?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;Model Armor&lt;/a&gt;, &lt;a href="https://docs.cloud.google.com/gemini-enterprise-agent-platform/optimize/observability/overview?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;telemetry&lt;/a&gt;, and &lt;a href="https://docs.cloud.google.com/gemini-enterprise-agent-platform/optimize/evaluation/agent-evaluation?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;agent evaluations&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fu8ujxz65dz7c17q6ui9u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fu8ujxz65dz7c17q6ui9u.png" alt="Gemini Enterprise Agent Platform" width="800" height="541"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Hybrid Execution Mode
&lt;/h3&gt;

&lt;p&gt;To support a fast local development cycle, the BFF supports two different run modes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Remote Execution Mode&lt;/strong&gt; : In staging and production, the BFF acts as a stateless proxy to the remote agent, running on the Google Agent Runtime.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Local Fallback Mode&lt;/strong&gt; : If no remote agent runtime ID is configured, FastAPI loads the agent code directly into the container and runs the ADK engine locally in a background thread, using the developer’s Application Default Credentials (ADC).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Project and Organisational Scope
&lt;/h3&gt;

&lt;p&gt;I want FinSavant to give me a holistic view across all the projects that are incurring cost against my billing account. But at the same time, I only want FinSavant to provide insights for projects that I actually have authority to see.&lt;/p&gt;

&lt;p&gt;But GCP resource hierarchies are rarely neat and tidy. Some of my projects live inside a nice, clean Google Cloud organisation, and some are &lt;em&gt;standalone&lt;/em&gt; — essentially orphaned projects floating in the ether that are linked to the billing account but don’t inherit anything from an organisation root.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ff74rb8fr5ygly01v26nh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ff74rb8fr5ygly01v26nh.png" alt="Projects with and without org" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To solve this, I designed a multi-layered discovery and security boundary:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Billing-Led Discovery&lt;/strong&gt; : Rather than scanning the Resource Manager from the top down (which misses standalone projects entirely), the backend starts by querying the Cloud Billing API to retrieve every project linked to our central billing account. This gives us a comprehensive list of all projects incurring costs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hierarchical Permission Resolution (With Caching)&lt;/strong&gt;: Once we have the master list of billing projects, we need to know what the user is actually allowed to see. The discovery service attempts a top-down interrogation:
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Org-Level Scan (Fast)&lt;/strong&gt;: If a target organisation ID is configured, the backend queries Cloud Asset Inventory’s IAM policies. This is extremely fast because it lets us resolve all of the user’s project bindings across the entire hierarchy in a single API call.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Project-Level Fallback (Granular)&lt;/strong&gt;: If organisation-wide access isn’t available or fails (as is often the case with standalone projects outside the org boundary), the service seamlessly falls back to a project-by-project scan, calling &lt;code&gt;getIamPolicy&lt;/code&gt; on each individual project in the billing list to compile the user's allowed set.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Performance Protection&lt;/strong&gt; : To prevent rate limits and quota exhaustion from repeating project-by-project IAM scans, this resolved set is cached in-memory with a thread-safe, 10-minute time-to-live (TTL).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;IAP-Enforced Row-Level Security&lt;/strong&gt; : We serve the React dashboard and agent chat through an Identity-Aware Proxy (IAP). When a user requests data, the BFF extracts their email from the &lt;code&gt;x-goog-authenticated-user-email&lt;/code&gt; header. It resolves their allowed projects list and sets it in a local context variable.&lt;/li&gt;
&lt;li&gt;To &lt;strong&gt;prevent prompt injections or the agent from hallucinating&lt;/strong&gt; data about projects the user shouldn’t see, we intercept all BigQuery billing queries and wrap them in a subquery that filters based on only the allowed projects. This means that even if the agent is querying the whole dataset, the database engine itself enforces strict row-level filtering based on the logged-in user’s identity. If the user only has access to one project, that’s all the agent can query.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Cloud Asset Inventory (CAI)
&lt;/h3&gt;

&lt;p&gt;I’m using CAI for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Zombie Detection&lt;/strong&gt; : I built custom CAI queries to instantly scan for unattached disks and idle external IPs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Detective Mode&lt;/strong&gt; : When we detect a cost spike, the agent uses CAI history to audit the exact configuration changes that occurred on that resource over the last 35 days. For example, detecting that an engineer upscaled a Cloud Run instance memory limit.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  BigQuery Tool Calls From Our Agents
&lt;/h3&gt;

&lt;p&gt;I want to be able to query my billing data — stored in BigQuery — using natural language prompts. I’m achieving this in two different ways, depending on where I’m coming from.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In my development workspace, I’m using the &lt;strong&gt;Google remote managed BigQuery MCP server&lt;/strong&gt; (&lt;a href="https://bigquery.googleapis.com/mcp" rel="noopener noreferrer"&gt;https://bigquery.googleapis.com/mcp&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;In our FinSavant ADK agent itself, I’m using &lt;strong&gt;ADK’s native&lt;/strong&gt; &lt;strong&gt;&lt;code&gt;BigQueryToolset&lt;/code&gt; directly&lt;/strong&gt;. In doing so, we simplify authentication, reduce runtime latency when making BQ calls, reduce dependency on an external service, and align with ADK best practices.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Developer Knowledge MCP
&lt;/h3&gt;

&lt;p&gt;To make FinSavant’s advice more than just generic feedback, we need to ground its recommendations in official Google Cloud engineering standards. That’s where the &lt;strong&gt;Developer Knowledge MCP&lt;/strong&gt; comes in.&lt;/p&gt;

&lt;p&gt;This MCP server provides a direct gateway to Google’s official developer documentation, product guides, API reference material, and the Cloud Architecture Framework. Instead of relying on the LLM’s static training data, the agent can query this knowledge base in real time to retrieve authoritative, up-to-date information.&lt;/p&gt;

&lt;p&gt;In FinSavant, we use the Developer Knowledge MCP to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Determine the Best Course of Action&lt;/strong&gt; : When the agent discovers a cost anomaly, it doesn’t just throw alerts. It queries the MCP to formulate an appropriate, structured response grounded in official documentation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Verify Architectural Best Practices&lt;/strong&gt; : It checks current Google Cloud design patterns, ensuring the agent doesn’t recommend legacy or non-optimal resource structures.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Provide Actionable Remediation&lt;/strong&gt; : If an idle persistent disk is flagged, the agent uses the MCP to outline the exact recommended steps to snapshot and clean up the asset safely, linking the user directly to the relevant documentation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Eliminate Hallucinations&lt;/strong&gt; : By grounding the agent in real-time documentation, we ensure any CLI commands or configuration snippets it presents are correct and match the latest GCP standards.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Let’s See It In Action!
&lt;/h2&gt;

&lt;p&gt;In this short video I demonstrate a number of FinSavant features, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Using starter chips to kick off an initial converation, e.g. looking for cost spikes over the last 30 days&lt;/li&gt;
&lt;li&gt;Seeing the various tools and MCP servers called in real time&lt;/li&gt;
&lt;li&gt;Seeing recommendations based on the findings&lt;/li&gt;
&lt;li&gt;Watching tiles and graph widgets being created in real time using A2UI&lt;/li&gt;
&lt;li&gt;Asking follow-up questions about particular projects&lt;/li&gt;
&lt;li&gt;Looking for other cost anomalies&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/zs_IRUxIx4E" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Cool, right?&lt;/p&gt;

&lt;h2&gt;
  
  
  What’s Next?
&lt;/h2&gt;

&lt;p&gt;In the next part of this series, we’ll get our hands dirty with &lt;strong&gt;Part 2: Building the Agentic Solution: Development with Google Antigravity, ADK, Agents CLI, MCP &amp;amp; Skills.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I’ll show you how to setup your development environment, how to boostrap ADK agents, and the code behind FinSavant.&lt;/p&gt;

&lt;p&gt;Stay tuned!&lt;/p&gt;

&lt;h2&gt;
  
  
  Before You Go
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Please share&lt;/strong&gt; this with anyone that you think will be interested. It might help them, and it really helps me!&lt;/li&gt;
&lt;li&gt;Please &lt;strong&gt;give me 50 claps&lt;/strong&gt;! (Just hold down the clap button.)&lt;/li&gt;
&lt;li&gt;Feel free to &lt;strong&gt;leave a comment&lt;/strong&gt;  💬.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Follow&lt;/strong&gt; and &lt;strong&gt;subscribe,&lt;/strong&gt; so you don’t miss my content.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Useful Links and References
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Project Code &amp;amp; Demo
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/derailed-dash/smart-gcp-finops" rel="noopener noreferrer"&gt;FinSavant Code on GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://youtu.be/zs_IRUxIx4E" rel="noopener noreferrer"&gt;FinSavant Demo on YouTube&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Gemini Enterprise Agent Platform &amp;amp; ADK
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.cloud.google.com/gemini-enterprise-agent-platform/overview?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;Gemini Enterprise Agent Platform Overview&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.cloud.google.com/gemini-enterprise-agent-platform/build/runtime?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;Agent Runtime (ADK Hosting)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.cloud.google.com/gemini-enterprise-agent-platform/build/adk?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;ADK Agent Building Guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://google.github.io/agents-cli/?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;Agents CLI Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://adk.dev/integrations/bigquery/?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;ADK BigQuery Tool Integration&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.cloud.google.com/agent-registry/overview?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;Agent Registry Overview&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.cloud.google.com/gemini-enterprise-agent-platform/scale/memory-bank?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;GEAP Memory Bank&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.cloud.google.com/gemini-enterprise-agent-platform/govern/gateways/agent-gateway-overview?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;Agent Gateway Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.cloud.google.com/model-armor/overview?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;Model Armor Security Overview&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.cloud.google.com/gemini-enterprise-agent-platform/optimize/observability/overview?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;GEAP Observability &amp;amp; Telemetry&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.cloud.google.com/gemini-enterprise-agent-platform/optimize/evaluation/agent-evaluation?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;Agent Evaluations&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Google Cloud Services &amp;amp; APIs
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.cloud.google.com/run/docs/overview/what-is-cloud-run?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;Cloud Run Overview&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.cloud.google.com/iap/docs/concepts-overview?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;Identity-Aware Proxy (IAP) Overview&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.cloud.google.com/cloud-assist/overview?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;Google Cloud Assist&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.cloud.google.com/asset-inventory/docs/overview?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;Cloud Asset Inventory (CAI) API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developers.google.com/knowledge/mcp?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;Developer Knowledge MCP Server&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  GCP Billing &amp;amp; FinOps
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.cloud.google.com/billing/docs/how-to/finops-hub?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;Google Cloud FinOps Hub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.cloud.google.com/billing/docs/how-to/export-data-bigquery?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;BigQuery Billing Exports Setup&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Articles &amp;amp; Resources
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://medium.com/google-cloud/using-google-identity-aware-proxy-iap-with-cloud-run-without-a-load-balancer-27db89b9ed49?sharedUserId=derailed.dash" rel="noopener noreferrer"&gt;Using Google IAP with Cloud Run without a Load Balancer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://cloud.google.com/blog/products/serverless/iap-integration-with-cloud-run?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;Cloud Run IAP Integration Announcement&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Portfolio
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dazbo.co.uk" rel="noopener noreferrer"&gt;Dazbo’s Portfolio&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>finops</category>
      <category>agentruntime</category>
      <category>googleadk</category>
      <category>geminienterprise</category>
    </item>
    <item>
      <title>Dialling Our Agents to 11: Agent Skills You Need to be Using!</title>
      <dc:creator>Darren "Dazbo" Lester</dc:creator>
      <pubDate>Mon, 15 Jun 2026 03:25:13 +0000</pubDate>
      <link>https://dev.to/gde/dialling-our-agents-to-11-agent-skills-you-need-to-be-using-2o2k</link>
      <guid>https://dev.to/gde/dialling-our-agents-to-11-agent-skills-you-need-to-be-using-2o2k</guid>
      <description>&lt;h2&gt;
  
  
  What This Article Is About
&lt;/h2&gt;

&lt;p&gt;Howdy friends!&lt;/p&gt;

&lt;p&gt;Recently I wrote an article called &lt;a href="https://dev.to/gde/dialling-our-agents-to-11-my-favourite-mcp-servers-3hbm"&gt;Dialling Our Agents to 11: My Favourite MCP Servers&lt;/a&gt;. It talked about how MCP servers and skills are essential components in transforming a simple agent into a useful, dependable, grounded and multi-skilled agent harness. I listed my favourite MCP servers for productivity, and promised a follow-up article that focuses on agent skills.&lt;/p&gt;

&lt;p&gt;Well, here it is!&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick Skills Recap
&lt;/h2&gt;

&lt;p&gt;If you don’t know what a skill is: &lt;strong&gt;think of it as a unit of knowledge and capability for an agent, loaded on-demand as required.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I recently did a talk on the topic of using &lt;strong&gt;MCP and skills to power-up our agents&lt;/strong&gt;. In April I &lt;a href="https://medium.com/@derailed.dash/my-incredible-google-cloud-next-26-experience-as-a-gde-1bd291cc3696" rel="noopener noreferrer"&gt;presented this at Google Next ’26 in Vegas&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://medium.com/@derailed.dash/my-incredible-google-cloud-next-26-experience-as-a-gde-1bd291cc3696" rel="noopener noreferrer"&gt;My Incredible Google Cloud Next 26 Experience as a GDE&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And in May I did a similar talk for &lt;a href="https://gdg.community.dev/events/details/google-gdg-prishtina-presents-build-with-ai-prishtina-from-ideas-to-impact/" rel="noopener noreferrer"&gt;Google Developer Group Prishtina&lt;/a&gt;, as part of the Google &lt;a href="https://developers.google.com/community/build-with-ai" rel="noopener noreferrer"&gt;&lt;em&gt;Build with AI&lt;/em&gt;&lt;/a&gt; roadshow.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://developers.google.com/community/build-with-ai" rel="noopener noreferrer"&gt;Build with AI | Google for Developers&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In that talk I explain &lt;strong&gt;what MCP and skills are, how they work, and how they differ&lt;/strong&gt;. I talk about the &lt;strong&gt;use cases&lt;/strong&gt; where skills are better than MCP servers and &lt;em&gt;vice versa,&lt;/em&gt; and I talk about the &lt;strong&gt;scenarios where you might want to use them together&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Here’s a recording of the BwAI session for GDG Prishtina:&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/tFUjc1Jx5_0" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Favourite Skills
&lt;/h2&gt;

&lt;p&gt;Time for me to talk about some of my favourite skills. I’ll explain what they are, how you use them, and how you install them.&lt;/p&gt;

&lt;p&gt;By the way, they’re free (and open source), and off-the-shelf; including a few created by me.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Google Agent Skills / Agents-CLI
&lt;/h2&gt;

&lt;p&gt;Let’s face it, building production-ready AI agents on Google Cloud used to feel like trying to build a functioning helicopter from a box of random Lego bricks. You had Vertex AI, sorry — I mean &lt;em&gt;Gemini Enterprise Agent Platform&lt;/em&gt;, Cloud Run, APIs, service accounts, IAM roles, and about a thousand vector store options. Your poor coding assistant would choke on the complexity, even if grounded with good quality documentation.&lt;/p&gt;

&lt;p&gt;The Google &lt;a href="https://google.github.io/agents-cli/" rel="noopener noreferrer"&gt;agents-cli&lt;/a&gt; is a game changer for this scenario. It’s a &lt;strong&gt;combined CLI and set of skills&lt;/strong&gt; for building, evaluating and deploying agents in Google Cloud. Now your assistant gets the exact API references, schemas, and scaffolding patterns it needs to build, test, and ship agents without having to guess the plumbing.&lt;/p&gt;

&lt;p&gt;Because it’s actually a combination of CLI and skills, we can use it in two ways:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;We can just run CLI commands directly from our terminal.&lt;/li&gt;
&lt;li&gt;We can use skills to inform our coding agent about how to use the CLI.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz9xfw2qlle0h1i4cqx5h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz9xfw2qlle0h1i4cqx5h.png" alt="agents-cli commands in the AI Development Lifecycle" width="799" height="263"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Setup
&lt;/h3&gt;

&lt;p&gt;Installation is a piece of cake. You can bootstrap the environment using uv — which, as you know, is my absolute favourite environment manager:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;uvx google-agents-cli setup
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Use
&lt;/h3&gt;

&lt;p&gt;With the CLI and skills installed, we can issue prompts like these to our coding agent:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;“&lt;/em&gt; &lt;strong&gt;&lt;em&gt;Build&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;a support agent that answers questions from our docs. I want to build using Agent Development Kit (ADK) and I want to deploy to Google Cloud eventually.”&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;“Write&lt;/em&gt; &lt;strong&gt;&lt;em&gt;evals&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;for the Rickbot agent and run them”&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;“&lt;/em&gt; &lt;strong&gt;&lt;em&gt;Deploy&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;this to Cloud Run”&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;“&lt;/em&gt; &lt;strong&gt;&lt;em&gt;Integrate&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;this with Gemini Enterprise”&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Past-Me&lt;/em&gt; used to build agents, run some unit tests, try a few manual prompts to the agent and declare: &lt;em&gt;“Yep, looks good to me!”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Don’t be &lt;em&gt;Past-Me&lt;/em&gt;. This agents-cli framework makes it so easy to add agentic reviews to your development process.&lt;/p&gt;

&lt;h3&gt;
  
  
  How Is it Different to Developer Knowledge and gcloud MCP Servers?
&lt;/h3&gt;

&lt;p&gt;If you are already using Google tools in your IDE, you might wonder how this fits in with the other tools at your disposal:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Google Developer Knowledge MCP (The Library 📚)&lt;/strong&gt;: A read-only lookup tool. It tells the agent &lt;em&gt;how&lt;/em&gt; GCP works (services, products, APIs and syntax) but doesn’t run commands or build resources.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;gcloud MCP (The Muscle 💪)&lt;/strong&gt;: Exposes low-level SDK commands. You supply natural language commands and your agent executes the gcloud commands to turn your wishes into reality. But has zero built-in understanding of agent architecture, ADK code, or prompt tuning.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But the Google &lt;strong&gt;agents-cli&lt;/strong&gt; is more like an orchestrator built specifically for the Agent Development Lifecycle (ADLC). And it knows how to leverage and deploy appropriate services in the Google Cloud ecosystem. It abstracts low-level GCP setup into single commands and adds agent-specific capabilities like evaluation runs and version trajectory grading.&lt;/p&gt;

&lt;h3&gt;
  
  
  Fun Fact
&lt;/h3&gt;

&lt;p&gt;The Google Agents-CLI has replaced the Google Agent Starter Pack.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Vercel Labs Find-Skills
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv9usksrxofgiibbjoig8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv9usksrxofgiibbjoig8.png" alt="find-skills" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Every great software ecosystem needs a package manager — think apt for Debian, npm for Node.js, uv for Python — and the AI agent world is no different. Enter the &lt;strong&gt;Skills CLI&lt;/strong&gt; (npx skills), a package manager developed by Vercel Labs. It lets you discover, install, and update modular packages (skills) that expand your agent’s capabilities.&lt;/p&gt;

&lt;p&gt;But wait! What’s the difference between the &lt;strong&gt;Skills CLI&lt;/strong&gt; and the &lt;strong&gt;find-skills skill&lt;/strong&gt;? It’s actually a really neat inception-style loop:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The Skills CLI (&lt;/strong&gt;&lt;strong&gt;npx skills)&lt;/strong&gt; is the command-line package manager tool itself (analogous to the npm binary). It is the mechanism that physically installs, checks, and updates skills on your machine.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The&lt;/strong&gt; &lt;strong&gt;find-skills skill&lt;/strong&gt; is the &lt;em&gt;on-demand knowledge&lt;/em&gt; that you install into your agent's brain using that package manager.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Without the find-skills skill loaded, if you ask your assistant: &lt;em&gt;"Hey, is there a skill to help me write Playwright E2E tests?"&lt;/em&gt;, the agent will just guess or tell you it doesn't know. Once you install the find-skills skill, it teaches your agent when and how to run the npx skills find CLI command on your behalf — allowing the agent to self-extend based on your requirements.&lt;/p&gt;

&lt;h3&gt;
  
  
  Setup
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx skills add https://github.com/vercel-labs/skills &lt;span class="nt"&gt;-y&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; - skill find-skills
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Use
&lt;/h3&gt;

&lt;p&gt;Once installed, you can search for capabilities directly using natural language. For instance:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;“Find and list some skills to help me write and maintain high quality software project documentation”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In response to this, the skill advises my agent (Antigravity) on the command to run, and prompts me for approval:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr1n91cvqz052mfb03xhu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr1n91cvqz052mfb03xhu.png" alt="Approval to run npx skills find" width="604" height="345"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It finds a bunch of skills (alas, not the skill I was hoping it would find — more on that later!), and asks if I want to install any of them:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo5by3l40ombmgswmpkcd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo5by3l40ombmgswmpkcd.png" alt="Finding skills" width="800" height="694"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Also, just like any other package manager, you can actually use npx skills and find-skills to update your set of skills. I only just found out this is possible!!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fianm4gu96njg54g30zcc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fianm4gu96njg54g30zcc.png" alt="Updating your skills" width="800" height="638"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Nice!&lt;/p&gt;

&lt;h3&gt;
  
  
  Pro Tip: &lt;strong&gt;Check the Leaderboard!&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Before you install a random skill, head over to &lt;a href="https://skills.sh" rel="noopener noreferrer"&gt;skills.sh&lt;/a&gt; to see the Open Skills leaderboard. This leaderboard automatically tracks open skills, along with GitHub metrics and the number of npx-based installs. From here, you can see the skills that are most popular and most trusted.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flpf34cx2skt3acob90h0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flpf34cx2skt3acob90h0.png" alt="skills.sh" width="800" height="597"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Dazbo Agent Skills
&lt;/h2&gt;

&lt;p&gt;Yes, I’m biased. But sometimes, you need a specialized toolset that addresses very specific workflows — which is exactly why I created my own suite of custom skills. But then, of course, I realised that these skills will often be useful to others, so I uploaded them to GitHub.&lt;/p&gt;

&lt;p&gt;The dazbo-agent-skills &lt;a href="https://github.com/derailed-dash/dazbo-agent-skills" rel="noopener noreferrer"&gt;repository&lt;/a&gt; is a curated collection of skills that I use often. In the box, you get:&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;&lt;code&gt;maintain-core-documentation&lt;/code&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;A specialist framework that guides the creation and maintenance of high quality core documentation files, including README.md, TODO.md, DESIGN.md (for Stitch-compatible UI spec), Architecture.md, Testing.md, and Deployment.md (for setup, Infra-as-Code, GitOps and CI/CD).&lt;/p&gt;

&lt;p&gt;It also leverages the &lt;em&gt;technical-writer&lt;/em&gt; skill, which I’ll mention later.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;&lt;code&gt;deploy-skills-in-antigravity&lt;/code&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;A global installer and relocator that automates adding or updating agent skills via npx and safely moves them to my preferred shared global path (&lt;code&gt;~/.gemini/skills/&lt;/code&gt;).&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;&lt;code&gt;convert-to-devto&lt;/code&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;A skill that automatically converts, structures and standardises Markdown files for publication on &lt;a href="http://dev.to"&gt;&lt;em&gt;dev.to&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Basically, it takes your input and reformats to the required &lt;em&gt;dev.to&lt;/em&gt; markdown format, including injection of the YAML frontmatter, formatting of inline variables, handling of nested code blocks, and converting links to &lt;em&gt;dev.to&lt;/em&gt;-compatible Liquid tags.&lt;/p&gt;

&lt;p&gt;Because I often post blogs like this on both &lt;a href="http://medium.com" rel="noopener noreferrer"&gt;Medium&lt;/a&gt; and &lt;a href="http://dev.to"&gt;dev.to&lt;/a&gt;, it saves me a huge amount of time in performing the appropriate conversion.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;&lt;code&gt;secrets-with-git-crypt&lt;/code&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Have you ever accidentally committed a local file that contained sensitive information, like an API key? I bet you’ve read some horror stories of what happens if you do! &lt;em&gt;(Like waking up to a five-figure cloud bill because your GCP credentials got scraped off GitHub within 30 seconds).&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This skill provides a workflow that leverages git-crypt — an open-source tool that enables transparent encryption and decryption of files in a Git repository using AES-256 encryption.&lt;/p&gt;

&lt;p&gt;I use this skill to ensure that if my repo has any files with sensitive configuration — like a &lt;code&gt;.env&lt;/code&gt; or &lt;code&gt;terraform.tfvars&lt;/code&gt;— the skill detects it, ensures it is ignored by git (by automatically adding to my &lt;code&gt;.gitignore&lt;/code&gt;), but also offers to create an encrypted version that will be stored in the repo. This is useful, because then the encrypted version can be pulled to any other machines I’m working on and decrypted locally. And the skill manages the decryption and synchronisation between encrypted and non-encrypted versions for me.&lt;/p&gt;

&lt;p&gt;Sure, you could just use a Secret Manager, or use GitHub secrets. But this approach is very convenient and operates completely transparently.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;&lt;code&gt;create-md-from-browsermcp-snapshot&lt;/code&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;One thing I often want to do is create a markdown version of a web page. This is especially useful for turning a page into quick, persistent context for my agent.&lt;/p&gt;

&lt;p&gt;Often, this is something that can be easily achieved using the &lt;em&gt;Browser Agent&lt;/em&gt; built into Antigravity. But sometimes this isn’t possible, and I’ve explained these scenarios &lt;a href="https://medium.com/google-cloud/dialling-our-agents-to-11-my-favourite-mcp-servers-9549c1442a5e" rel="noopener noreferrer"&gt;here&lt;/a&gt;. In these scenarios, I use BrowserMCP to remote control and read a specific Chrome browser tab. But the BrowserMCP tools are not natively able to create markdown. And so I created a skill which executes Python to turn the BrowserMCP JSON output into high-fidelity markdown.&lt;/p&gt;

&lt;h3&gt;
  
  
  Setup
&lt;/h3&gt;

&lt;p&gt;You can install all these skills in one hit, or just install the ones that look most interesting to you:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# All Dazbo skills&lt;/span&gt;
npx skills add https://github.com/derailed-dash/dazbo-agent-skills &lt;span class="nt"&gt;-y&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt;

&lt;span class="c"&gt;# Installing a specific Dazbo skill&lt;/span&gt;
npx skills add https://github.com/derailed-dash/dazbo-agent-skills &lt;span class="nt"&gt;-y&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; &lt;span class="nt"&gt;--skill&lt;/span&gt; maintaining-core-documentation
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  If You Like These Skills…
&lt;/h3&gt;

&lt;p&gt;Please add a star to my &lt;a href="https://github.com/derailed-dash/dazbo-agent-skills" rel="noopener noreferrer"&gt;repo&lt;/a&gt;!&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Google Skills
&lt;/h2&gt;

&lt;p&gt;If you are building systems on Google Cloud, you don’t want your AI assistant to guess how to configure your databases or auto-scale your clusters. You want the official blueprints.&lt;/p&gt;

&lt;p&gt;The official &lt;a href="https://github.com/google/skills" rel="noopener noreferrer"&gt;Google Skills repository&lt;/a&gt; (google/skills) is a collection of skills that provide AI agents with precise, up-to-date knowledge of Google Cloud services and architectural standards. And since they exist as multiple skills with well-defined narrow scopes, they’re only loaded when you’re working on a relevant service.&lt;/p&gt;

&lt;p&gt;With these installed, you’ll find that agent output is much higher quality, token usage goes down considerably, and the number of loops required to achieve a goal is also reduced. It will save you time and money!&lt;/p&gt;

&lt;h3&gt;
  
  
  What’s in the Box?
&lt;/h3&gt;

&lt;p&gt;To help make sense of the repository, the skills are categorised into three main logical groups:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw471d4mrm7v6feyg5ylk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw471d4mrm7v6feyg5ylk.png" alt="Google Skills — Full list" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Agent Platform Skills:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;agent-platform-deploy&lt;/code&gt;&lt;/strong&gt; : Automates the packaging and deployment of AI agents to Google Cloud platforms (like Cloud Run or GKE) with proper service bindings.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;agent-platform-endpoint-management&lt;/code&gt;&lt;/strong&gt; : Configures and manages Vertex AI model endpoints, routing, and access control.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;agent-platform-eval-flywheel&lt;/code&gt;&lt;/strong&gt; : Sets up continuous evaluation pipelines for monitoring agent response quality over time.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;agent-platform-inference&lt;/code&gt;&lt;/strong&gt; : Directs optimal model invocation patterns, including parameter tuning, fallback models, and token budget management.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;agent-platform-migrate-from-ai-studio&lt;/code&gt;&lt;/strong&gt; : Streamlines porting agent prompts and configs from Google AI Studio to enterprise Vertex AI environments.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;agent-platform-model-registry&lt;/code&gt;&lt;/strong&gt; : Tracks and organises different versions of foundation and tuned models within Vertex AI.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;agent-platform-prompt-management&lt;/code&gt;&lt;/strong&gt; : Version-controls system prompts, system instructions, and few-shot examples independently of the application code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;agent-platform-rag-engine-management&lt;/code&gt;&lt;/strong&gt; : Guides the configuration of document chunking, indexing, and vector database retrieval settings for grounding.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;agent-platform-skill-registry&lt;/code&gt;&lt;/strong&gt; : Manages the life cycle of installed agent tools and skills, ensuring correct schema definitions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;agent-platform-tuning-management&lt;/code&gt;&lt;/strong&gt; : Oversees model tuning jobs, tracking parameters, and comparing metrics across different runs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;agent-platform-tuning&lt;/code&gt;&lt;/strong&gt; : Provides instructions for formatting datasets and executing supervised fine-tuning (SFT) jobs for Gemini models.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Core Services &amp;amp; APIs:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;alloydb-basics&lt;/code&gt;&lt;/strong&gt; : Scaffolds and optimises Google's enterprise-grade PostgreSQL-compatible database, including pgvector setup.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;bigquery-basics&lt;/code&gt;&lt;/strong&gt; : Guides dataset creation, partitioning, clustering, and writing optimised SQL queries for massive data analysis.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;cloud-run-basics&lt;/code&gt;&lt;/strong&gt; : Handles containerised application deployment, scaling configurations, and setting up HTTPS endpoints in seconds.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;cloud-sql-basics&lt;/code&gt;&lt;/strong&gt; : Scaffolds and secures managed database instances (PostgreSQL, MySQL, SQL Server) in Google Cloud.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;firebase-basics&lt;/code&gt;&lt;/strong&gt; : Scaffolds mobile/web backends, including Firestore database rules, Authentication, and Cloud Storage setup.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;gcloud&lt;/code&gt;&lt;/strong&gt; : Bridges the gap between your coding agent and low-level CLI infrastructure commands, ensuring correct flags and parameters.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;gemini-agents-api&lt;/code&gt;&lt;/strong&gt; : Guides integration with Vertex AI Agent Builder APIs for orchestrating pre-built agentic workflows.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;gemini-api&lt;/code&gt;&lt;/strong&gt; : Formulates correct payloads, system instructions, and schema definitions for the Gemini developer API.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;gemini-interactions-api&lt;/code&gt;&lt;/strong&gt; : Configures chat history buffers, session state persistence, and conversational turn-taking logic.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;gke-basics&lt;/code&gt;&lt;/strong&gt; : Scaffolds Google Kubernetes Engine clusters, container deployments, ingress controllers, and namespace isolation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;workload-manager-basics&lt;/code&gt;&lt;/strong&gt; : Evaluates, configures, and runs best-practice checks on complex cloud workloads (like SAP or high-performance computing).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Well-Architected Framework (WAF), Recipes and Operations:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;google-cloud-networking-observability&lt;/code&gt;&lt;/strong&gt; : Guides setting up VPC Flow Logs, Connectivity Tests, and Network Intelligence Center dashboards.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;google-cloud-recipe-auth&lt;/code&gt;&lt;/strong&gt; : Implements best-practice authentication flows, from simple API keys to complex OAuth2 and service accounts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;google-cloud-recipe-onboarding&lt;/code&gt;&lt;/strong&gt; : Automates initial GCP landing zone setup, including IAM bindings, project creation, and resource hierarchies.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;google-cloud-waf-cost-optimization&lt;/code&gt;&lt;/strong&gt; : Aligns setups with Google's cost-saving principles (like rightsizing, billing alerts, and lifecycle rules).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;google-cloud-waf-operational-excellence&lt;/code&gt;&lt;/strong&gt; : Configures monitoring dashboards, alerts, health checks, and structured logging policies.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;google-cloud-waf-performance-optimization&lt;/code&gt;&lt;/strong&gt; : Guides resource profiling, caching strategies, database indexing, and low-latency network setups.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;google-cloud-waf-reliability&lt;/code&gt;&lt;/strong&gt; : Configures multi-region failovers, automated backups, load balancers, and disaster recovery strategies.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;google-cloud-waf-security&lt;/code&gt;&lt;/strong&gt; : Enforces Least Privilege access, identity federation, secret rotation, and data encryption at rest and in transit.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;google-cloud-waf-sustainability&lt;/code&gt;&lt;/strong&gt; : Details carbon footprint tracking and architecting workloads to minimise compute-hour waste.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  How do “Agent Platform Skills” Differ from “Google Agent Skills”?
&lt;/h3&gt;

&lt;p&gt;With Google agent skills appearing in two sections, you may be wondering how they differ.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;strong&gt;Google Agent Skills&lt;/strong&gt; are focussed on the developer workflow. They help our developer agent to know how to build, scaffold, evaluate, and deploy agents, leveraging the Agents-CLI.&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;Agent Platform Skills&lt;/strong&gt; from the Google Skills repo are focused on the underlying architectural blueprints of Gemini Enterprise Agent Platform services. They teach the agent how to configure the platform control plane, such as setting up RAG, vector stores, and model fine-tuning jobs.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In short: Google Agents Skills help you to build and run agents; Agent Platform Skills give us the deep system capabilities and blueprints.&lt;/p&gt;

&lt;h3&gt;
  
  
  Setup
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# To install all the skills&lt;/span&gt;
npx skills add https://github.com/google/skills &lt;span class="nt"&gt;-y&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt;

&lt;span class="c"&gt;# To install an individual skill (e.g. alloydb-basics)&lt;/span&gt;
npx skills add https://github.com/google/skills &lt;span class="nt"&gt;-y&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; &lt;span class="nt"&gt;--skill&lt;/span&gt; alloydb-basics
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Pro Tip
&lt;/h3&gt;

&lt;p&gt;By keeping these skills installed globally, you ensure that if you ask your assistant to design a BigQuery schema or secure a Cloud Run service, it automatically references the exact WAF parameters without you having to copy-paste documents.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Awesome Agent Skills
&lt;/h2&gt;

&lt;p&gt;If you’re looking for the Swiss Army knife of specialised agent capabilities, my buddy &lt;strong&gt;Shubham Saboo&lt;/strong&gt; has built an absolute goldmine. His repository, &lt;a href="https://github.com/shubhamsaboo/awesome-llm-apps" rel="noopener noreferrer"&gt;&lt;strong&gt;awesome-llm-apps&lt;/strong&gt;&lt;/a&gt;, is incredibly popular in the AI engineering community — sitting at a staggering 114,000+ stars on GitHub!&lt;/p&gt;

&lt;p&gt;While the repo started as a showcase for RAG and agent patterns, it also includes a dedicated &lt;code&gt;awesome_agent_skills&lt;/code&gt; directory. The goal of this collection is to provide developers with modular, plug-and-play skills that teach AI assistants how to handle specific tasks with professional-grade precision.&lt;/p&gt;

&lt;p&gt;If you browse the Open Skills leaderboard on &lt;a href="https://skills.sh" rel="noopener noreferrer"&gt;skills.sh&lt;/a&gt;, you’ll find that Shubham’s skills are frequently trending near the top. According to the registry, the top 5 most popular skills from his package are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;deep-research&lt;/code&gt;&lt;/strong&gt; — Highly installed for conducting comprehensive, multi-source investigations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;fact-checker&lt;/code&gt;&lt;/strong&gt; — A specialised claim-verification tool.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;technical-writer&lt;/code&gt;&lt;/strong&gt; — For generating developer-friendly API references and guides.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;debugger&lt;/code&gt;&lt;/strong&gt; — A systematic troubleshooting skill for bug isolation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;fullstack-developer&lt;/code&gt;&lt;/strong&gt; — Blueprints for web development covering React, Next.js, and database architectures.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let’s do a mild deep dive into the three skills I use most often in my own workflows…&lt;/p&gt;

&lt;h3&gt;
  
  
  Deep Research
&lt;/h3&gt;

&lt;p&gt;For conducting thorough investigations and synthesising multiple perspectives with clean citations, the &lt;code&gt;deep-research&lt;/code&gt; skill acts as your agent’s private investigator.&lt;/p&gt;

&lt;p&gt;It instructs the agent to break down a complex, open-ended query into smaller, logical subtopics. The agent then gathers and cross-references information from multiple sources, eventually generating a structured research report. The output is complete with an executive summary, detailed breakdowns, consensus vs. debate analyses, and inline citations pointing to original sources.&lt;/p&gt;

&lt;p&gt;To install it globally:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx skills add https://github.com/shubhamsaboo/awesome-llm-apps/awesome-agent-skills &lt;span class="nt"&gt;-y&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; &lt;span class="nt"&gt;--skill&lt;/span&gt; deep-research
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Fact Checker
&lt;/h3&gt;

&lt;p&gt;The ultimate BS detector.&lt;/p&gt;

&lt;p&gt;If you need to verify statistics, cross-reference claims, or check for potential bias or misinformation in a document, the &lt;code&gt;fact-checker&lt;/code&gt; skill is your go-to.&lt;/p&gt;

&lt;p&gt;It teaches your agent to dissect text into testable assertions and evaluate them using a strict, evidence-based scale — ranging from ✅ TRUE to 🚫 FALSE. It is particularly good at spotting subtle logical fallacies, statistics pulled out of context, and missing caveats.&lt;/p&gt;

&lt;p&gt;To install it globally:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx skills add https://github.com/shubhamsaboo/awesome-llm-apps/awesome-agent-skills &lt;span class="nt"&gt;-y&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; &lt;span class="nt"&gt;--skill&lt;/span&gt; fact-checker
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Technical Writer
&lt;/h3&gt;

&lt;p&gt;Clear documentation is a developer’s superpower, but writing it is often a chore. The &lt;code&gt;technical-writer&lt;/code&gt; skill gives your agent the exact templates and principles needed to write high-quality technical guides.&lt;/p&gt;

&lt;p&gt;It directs the agent to write using a clear, active voice in the present tense. Crucially, it enforces the principle of &lt;em&gt;progressive disclosure&lt;/em&gt; — structuring documents so that the quick-start guide, code snippets, and interactive examples appear &lt;em&gt;first&lt;/em&gt;, while the massive, dry reference tables and configurations are pushed to the end of the document.&lt;/p&gt;

&lt;p&gt;Fun fact: my own &lt;code&gt;maintain-core-documentation&lt;/code&gt; skill actually makes use of the &lt;code&gt;technical-writer&lt;/code&gt; skill, if it can. (It will offer to install it, if it’s not yet installed.)&lt;/p&gt;

&lt;p&gt;To install it globally:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx skills add https://github.com/shubhamsaboo/awesome-llm-apps/awesome-agent-skills &lt;span class="nt"&gt;-y&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; &lt;span class="nt"&gt;--skill&lt;/span&gt; technical-writer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  6. Remotion Best Practices
&lt;/h2&gt;

&lt;p&gt;If you’ve ever tried to generate programmatic videos, you probably ended up writing spaghetti scripts calling ffmpeg command strings that looked like ancient hieroglyphics.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.remotion.dev/" rel="noopener noreferrer"&gt;&lt;strong&gt;Remotion&lt;/strong&gt;&lt;/a&gt; changes the game by letting you build real, high-quality MP4 videos using React components, HTML, and CSS. The &lt;code&gt;remotion-best-practices&lt;/code&gt; skill provides coding assistants with the complete ruleset for scaffolding, animating, and rendering Remotion videos safely.&lt;/p&gt;

&lt;h3&gt;
  
  
  What’s Inside the Box?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Project Scaffolding:&lt;/strong&gt; Instructions on bootstrapping clean projects immediately&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Animation Rules:&lt;/strong&gt; Animating elements mathematically.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Asset Handling:&lt;/strong&gt; Enforces using Remotion’s specialized media components (&lt;code&gt;&amp;lt;Img&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;Video&amp;gt;&lt;/code&gt;, and &lt;code&gt;&amp;lt;Audio&amp;gt;&lt;/code&gt; from &lt;code&gt;@remotion/media&lt;/code&gt;) wrapped in the &lt;code&gt;staticFile()&lt;/code&gt; helper to reference files in the local &lt;code&gt;/public&lt;/code&gt; folder.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Studio &amp;amp; Rendering:&lt;/strong&gt; Commands to start the local preview server (&lt;code&gt;npx remotion studio&lt;/code&gt;) and render single frames to sanity-check layouts.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Setup
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx skills add https://github.com/remotion-dev/skills &lt;span class="nt"&gt;-y&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; &lt;span class="nt"&gt;--skill&lt;/span&gt; remotion-best-practices
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Typical Use Cases for Remotion
&lt;/h3&gt;

&lt;p&gt;Remotion is an absolute game-changer in scenarios where you need to move beyond desktop editors and build scalable video pipelines:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Personalised Video Reels&lt;/strong&gt; : Generating user-specific analytics videos (like “Year-in-Review” summaries) or custom onboarding clips dynamically at run time.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Real-time Content Teasers&lt;/strong&gt; : Turning text articles, RSS feeds, or news updates into short video summaries and teasers for social media automatically.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Interactive Parameter Editing&lt;/strong&gt; : Building interfaces where non-technical users can tweak text, colors, or transitions and preview renders instantly in their browser.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Headless Rendering Pipelines&lt;/strong&gt; : Running serverless video rendering to stitch clips, apply dynamic watermarks, and spit out MP4s programmatically.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Real-World Example: Prompt-to-Video Engine
&lt;/h3&gt;

&lt;p&gt;To see just how powerful the combination of AI and Remotion is, I asked my coding assistant to build a working prototype: &lt;strong&gt;a Prompt-to-Video Engine&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;“Create a 15-second teaser for Antigravity, an agent first development environment for turning ideas into reality, built on Google Gemini technology. Let’s turn months into minutes. Dark theme. Pull in Google Antigravity visuals.”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In response to this prompt, the coding assistant leveraged the &lt;code&gt;remotion-best-practices&lt;/code&gt; skill to implement the following system:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;The Generator (&lt;code&gt;generate_video.py&lt;/code&gt;)&lt;/strong&gt;: A Python script that uses the modern &lt;code&gt;google-genai&lt;/code&gt; SDK and Pydantic validation to translate my prompt into a structured JSON configuration (&lt;code&gt;video-data.json&lt;/code&gt;), selecting dark-mode colors, highlights, and scene copy. It automatically authenticates via Google Cloud Vertex AI or Developer APIs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Remotion Template (&lt;code&gt;VideoTemplate.tsx&lt;/code&gt;)&lt;/strong&gt;: A parameterised React component that reads the generated JSON configuration, imports modern typography dynamically using &lt;code&gt;@remotion/google-fonts&lt;/code&gt;, and applies custom Bézier animation curves (&lt;code&gt;interpolate&lt;/code&gt;) to animate headings, dividers, and body copy frame-by-frame.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dynamic Composition (&lt;code&gt;Root.tsx&lt;/code&gt;)&lt;/strong&gt;: Configured to dynamically compute the video's total frames based on the scene durations returned by Gemini.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The agent then generated a still image from one second in, to test the application:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frs7ijpjpi23irmv1spma.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frs7ijpjpi23irmv1spma.png" alt="Still created by the Remotion Demo" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And then it went ahead and created the full 15 second video.&lt;/p&gt;

&lt;p&gt;If I wanted to edit the video and re-generate, it would be as simple as asking the agent to update the application, or I could just manually edit the scene file that the agent created for me:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"background_color"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"#0D0E15"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"accent_color"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"#6366F1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"text_color"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"#F3F4F6"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"scenes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Ideas Grounded?"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"subtitle"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Traditional development slows innovation. Complex, manual, frustrating."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"duration_secs"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;3.5&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Antigravity: Agent-First"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"subtitle"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Powered by Google Gemini. Intelligent agents transform concepts into reality."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"duration_secs"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;4.5&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Months to Minutes"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"subtitle"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Accelerate from vision to deployed product at unprecedented speed. Build smarter."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"duration_secs"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;4.0&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Antigravity."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"subtitle"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Your ideas, unleashed. Experience the future of development."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"duration_secs"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;3.0&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  7. Google Genmedia Skills
&lt;/h2&gt;

&lt;p&gt;In &lt;a href="https://medium.com/google-cloud/dialling-our-agents-to-11-my-favourite-mcp-servers-9549c1442a5e" rel="noopener noreferrer"&gt;Part 1 of this miniseries&lt;/a&gt;, I explored several media-focussed MCP servers, such as &lt;code&gt;avtool&lt;/code&gt; (which wraps the command-line Swiss Army knife &lt;code&gt;ffmpeg&lt;/code&gt;), &lt;code&gt;chirp3-hd&lt;/code&gt; (for high-fidelity speech synthesis), and &lt;code&gt;lyria&lt;/code&gt; (for generative music).&lt;/p&gt;

&lt;h3&gt;
  
  
  But Why Do We Need the Skills?
&lt;/h3&gt;

&lt;p&gt;You might wonder: &lt;em&gt;if my agent has access to&lt;/em&gt; &lt;code&gt;avtool&lt;/code&gt; &lt;em&gt;and therefore&lt;/em&gt; &lt;code&gt;ffmpeg&lt;/code&gt; &lt;em&gt;commands via MCP, why does it need skills?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Whilst those servers provide the raw capabilities — the “hands and eyes” to manipulate media files — they do not teach the agent &lt;em&gt;how&lt;/em&gt; to compose media like a professional.&lt;/p&gt;

&lt;p&gt;That is where the &lt;a href="https://github.com/GoogleCloudPlatform/vertex-ai-creative-studio/tree/main/experiments/mcp-genmedia/skills" rel="noopener noreferrer"&gt;&lt;strong&gt;Google Genmedia Skills&lt;/strong&gt;&lt;/a&gt; come in. These skills supply the procedural knowledge, prompt blueprints, and guardrails necessary to transform a basic coding assistant into a competent, multi-talented media showrunner.&lt;/p&gt;

&lt;p&gt;Let’s look at the difference between &lt;strong&gt;atomic tasks&lt;/strong&gt; and &lt;strong&gt;composite creative tasks&lt;/strong&gt; :&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Atomic Task Scenario: MCP is Sufficient&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Suppose you ask the agent:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;“Extract the first 10 seconds of this video and save it as a new clip.”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This is a straightforward, single-step operation. The agent simply looks at the tools exposed by the &lt;code&gt;avtool&lt;/code&gt; MCP server, identifies the correct command, and executes a standard &lt;code&gt;ffmpeg&lt;/code&gt; trim. No special domain expertise or workflow management is required. The raw MCP server is perfectly sufficient.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Composite Creative Task — Skills Required&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now suppose you give a more complex prompt:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;“Generate a 15-second promotional clip using a warm narrator voiceover, a low-key background music track, and place our company logo watermark in the bottom-right corner. Make sure the video loops cleanly if the audio runs slightly over.”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Without specialised skills, a naive agent will likely fail in several ways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Audio clashing:&lt;/strong&gt; It will layer the narrator and background music at default volumes, resulting in a loud, unintelligible mess. (No vocal boosting; no music ducking.)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Watermark coordinate guesswork:&lt;/strong&gt; It will try to overlay the logo image at a random coordinate, likely cropping it or placing it off-screen, since it doesn’t know it must first probe the video dimensions and calculate the offset mathematically.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Audio-video desync:&lt;/strong&gt; If the voiceover runs to 16.5 seconds, the 15-second video will abruptly cut off or loop incorrectly, ruining the pacing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unrefined prompts:&lt;/strong&gt; It will send a dry, text prompt to Gemini TTS or Imagen, resulting in a flat, robotic voiceover and a generic style.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Genmedia skills solve this by encoding the exact workflows, volume offsets, and coordinate calculations used by real video editors and audio engineers, guiding the agent to orchestrate these tool calls systematically.&lt;/p&gt;

&lt;h3&gt;
  
  
  What’s Inside the Box?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;genmedia-producer&lt;/code&gt;&lt;/strong&gt; : The master orchestrator for complex multi-step media workflows. It guides the agent through storyboarding, script sanitisation (such as removing markdown syntax before synthesis), and matching video total runtime with audio duration.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;genmedia-video-editor&lt;/code&gt;&lt;/strong&gt; : Expert knowledge in FFmpeg composition. It handles video stitching, two-pass high-quality GIF generation, and teaches the agent how to mathematically calculate watermark coordinates after querying media dimensions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;genmedia-audio-engineer&lt;/code&gt;&lt;/strong&gt; : Specialist in high-fidelity speech synthesis, music generation, and multi-track mixing. It instructs the agent on professional volume adjustments — boosting voiceovers while lowering background music — and ensuring sample rates match to prevent pitch shifts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;genmedia-image-artist&lt;/code&gt;&lt;/strong&gt; : A direct line to Gemini image generation. It guides prompt building using professional terminology (like "chiaroscuro" lighting or "bokeh" lens effects) and handles collaborative, iterative refinements using multimodal inputs (like PDFs or video reference frames).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;genmedia-voice-director&lt;/code&gt;&lt;/strong&gt; : Expert director for virtual voice actors. It instructs the agent to treat Gemini TTS as talent, setting detailed scenes and using bracketed inline audio tags (like [sigh], [laughs], [enthusiasm], or [long pause]) within transcripts to shape realistic, emotional delivery.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;story-generator&lt;/code&gt;&lt;/strong&gt; : A heavy-duty, feedback-driven media engine that orchestrates parallel subagents to build full multi-scene storybooks (complete with images, video, voice, and music).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Setup
&lt;/h3&gt;

&lt;p&gt;To install the Genmedia skills suite globally:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx skills add https://github.com/GoogleCloudPlatform/vertex-ai-creative-studio/experiments/mcp-genmedia/skills &lt;span class="nt"&gt;-y&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Real Demo
&lt;/h3&gt;

&lt;p&gt;Let’s take the 15 second video I created with Remotion, and then use the GenMedia skills to add an audio track:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;“Using the GenMedia skills, generate a 15-second ambient, futuristic electronic synth track matching the duration of our teaser video &lt;code&gt;out.mp4&lt;/code&gt;. Mix this music track into the video as background audio using &lt;code&gt;avtool&lt;/code&gt;, set the music volume to a subtle level (e.g. -18dB) so it doesn't overpower, and output the final file to &lt;code&gt;media-output/agy_teaser_with_music.mp4&lt;/code&gt;."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;First, Agy asks for permission to use Lyria:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs7wazvq20n2owfuanfyo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs7wazvq20n2owfuanfyo.png" alt="Seeking approval for Lyria" width="769" height="886"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then it prompts to allow avtool. And then, after no more than about 5 seconds of work:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7q8uiq57twe3pki2a6ph.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7q8uiq57twe3pki2a6ph.png" alt="Video synthesised!" width="742" height="457"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let’s add a voiceover.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;“Now, using GenMedia skills, please add a professional voiceover over the top. English female voice. Render the new video as &lt;code&gt;agy_teaser_with_music_and_voiceover&lt;/code&gt;. The voice over should just include the main punchy statements from each scene.”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;And the result:&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/Sb52hjvZuS4" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Insane! All done in less than 5 minutes.&lt;/p&gt;

&lt;p&gt;Of course, we could have just generated the whole video with Veo, or even Google Flow. But producing the original video with Remotion gives us a deterministic result with very specific aesthetic controls.&lt;/p&gt;

&lt;h2&gt;
  
  
  8. Google Data Agent Kit
&lt;/h2&gt;

&lt;p&gt;If you are a data engineer or data scientist, a huge portion of your day is likely spent on the “tab-hopping” loop — jumping between the BigQuery console, Python notebooks, dbt terminals, and your AI chat window. Google’s open-source &lt;strong&gt;Data Agent Kit (DAK)&lt;/strong&gt; is designed to a) eliminate this context-switching fatigue and b) give your agent knowledge of best practices for all of the various data services in the Google ecosystem.&lt;/p&gt;

&lt;p&gt;By embedding live metadata access and MCP tools directly into your IDE, DAK gives your coding agent a direct line of sight into your Google Cloud data estate. DAK integrates natively with Antigravity IDE and VS Code, via the &lt;a href="https://marketplace.visualstudio.com/items?itemName=GoogleCloudTools.datacloud" rel="noopener noreferrer"&gt;Google Cloud Data Agent Kit&lt;/a&gt; extension.&lt;/p&gt;

&lt;h3&gt;
  
  
  What’s Inside the Box?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Unified Data Estate Hub:&lt;/strong&gt; Consolidates databases (AlloyDB for PostgreSQL, Cloud SQL, Spanner) and storage (Google Cloud Storage) into a single, cohesive view inside the IDE.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A set of agent skills:&lt;/strong&gt; relating to Google data services.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Conversational analytics:&lt;/strong&gt; Run natural language queries to profile, search, and visualize BigQuery datasets, with the ability to generate LookML models or Streamlit dashboards.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automated pipeline assembly:&lt;/strong&gt; Instruct your agent to construct end-to-end data workflows. The agent programmatically builds the Apache Spark notebooks for ingestion, dbt projects for bronze → silver → gold transformations, and scheduled orchestration pipelines (like Apache Airflow and Dataflow).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Intelligent workload routing:&lt;/strong&gt; Automatically routes data tasks to the optimal engine — SQL-native ELT operations land on BigQuery, while custom Python transformations and distributed ML training are directed to Spark.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Incident diagnosis &amp;amp; autonomous recovery:&lt;/strong&gt; If a pipeline fails in production, the kit runs root-cause analyses, drafts fixes, tests them, and redeploys the jobs autonomously.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Setup &amp;amp; Installation
&lt;/h3&gt;

&lt;p&gt;Unlike the other skills I’ve listed so far, this the DAK is a much more holistic integration with your IDE. You install the Data Agent Kit from the Extensions Marketplace in VS Code or Antigravity IDE. You can install the extension directly from the Extensions view:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1h0kyaxrs19dl5atp7nx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1h0kyaxrs19dl5atp7nx.png" alt="Installing Google Cloud Data Agent Kit in Antigravity" width="688" height="346"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  What Do You See in the IDE?
&lt;/h3&gt;

&lt;p&gt;After installing, you’ll see:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The Unified Data Estate Hub:&lt;/strong&gt; A new Google Cloud Data Agent Kit icon appears in your left-hand activity bar. Clicking it opens a dedicated sidebar explorer that consolidates your BigQuery datasets, Cloud Storage buckets, Spanner/AlloyDB/Cloud SQL instances, and Dataproc notebooks. If you are not yet authenticated, a sign-in prompt is pinned to the bottom status bar to guide you.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A bunch of agent skills&lt;/strong&gt; :&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwmm9vnaskc7cku9v81kr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwmm9vnaskc7cku9v81kr.png" alt="Skills installed by the Data Agent Kit" width="595" height="709"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Auto-provisioned MCP tools:&lt;/strong&gt; Rather than forcing you to manually run npx skills add to register skills one-by-one, the extension automatically provisions a suite of remote and local Model Context Protocol (MCP) servers (like &lt;code&gt;datacloud_bigquery_remote&lt;/code&gt; or &lt;code&gt;datacloud_spanner_remote&lt;/code&gt;) directly into Antigravity's agent harness. When you chat with the agent or query /mcp, these tools are instantly active — empowering the agent to inspect schemas, write dbt transformations, or run query-optimisation analyses on your behalf.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcskn6u4couae7vco2ec9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcskn6u4couae7vco2ec9.png" alt="Auto-Provisioned Remote MCP Servers" width="800" height="609"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;So, there you have it; a whistle-stop tour of my absolute favourite agent skills that are currently transforming the way I build, test, and run things.&lt;/p&gt;

&lt;p&gt;And you’ll notice that these skills work in a number of ways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Some are standalone and simply provide your agents with guidance.&lt;/li&gt;
&lt;li&gt;Some include embedded scripts — such as bash or Python code — and execute these scripts when required.&lt;/li&gt;
&lt;li&gt;Some go hand-in-hand with other tools, such as locally installed CLIs or MCP servers. This combo is especially powerful, because the tools provide all the capabilities our agents need, whilst the complementary skills advise our agents on how to use those tools effectively.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Whether you’re bootstrapping GCP resources with agents-cli, self-extending your assistant’s capabilities with find-skills, or orchestrating headless video pipelines via Remotion and Genmedia — loading the right skills on-demand is the secret to dialling your agents to 11.&lt;/p&gt;

&lt;p&gt;So, what are you waiting for? Install a few of these, power-up your IDE, and let me know how you get on.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Are Your Favourites?
&lt;/h2&gt;

&lt;p&gt;Please, tell me what skills you use. Post in the comments. Let's crowd-source a great set of useful skills!&lt;/p&gt;

&lt;h2&gt;
  
  
  Before You Go
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Please share&lt;/strong&gt; this with anyone that you think will be interested. It might help them, and it really helps me!&lt;/li&gt;
&lt;li&gt;Please &lt;strong&gt;interact&lt;/strong&gt;!&lt;/li&gt;
&lt;li&gt;Feel free to &lt;strong&gt;leave a comment&lt;/strong&gt; 💬.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Follow&lt;/strong&gt; and &lt;strong&gt;subscribe,&lt;/strong&gt; so you don’t miss my content.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Useful Links and References
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Skills and MCP
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://medium.com/google-cloud/dialling-our-agents-to-11-my-favourite-mcp-servers-9549c1442a5e" rel="noopener noreferrer"&gt;Dialling Our Agents to 11: My Favourite MCP Servers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=tFUjc1Jx5_0" rel="noopener noreferrer"&gt;Skills and MCP Servers Explained (Build with AI, Prishtina)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/google-cloud/configuring-mcp-servers-and-skills-for-antigravity-cli-and-ide-a938c7eebb78" rel="noopener noreferrer"&gt;Configuring MCP Servers and Skills for Antigravity CLI and IDE&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://skills.sh" rel="noopener noreferrer"&gt;Skills.sh — The Open Skills Ecosystem&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/shubhamsaboo/awesome-llm-apps" rel="noopener noreferrer"&gt;awesome-llm-apps&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.remotion.dev/" rel="noopener noreferrer"&gt;Remotion&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Tools, Frameworks and Environment
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://antigravity.google/product/antigravity-cli?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;Antigravity CLI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;Antigravity IDE&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://antigravity.google/docs/getting-started?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;Antigravity Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://adk.dev/?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;Google Agent Development Kit (ADK)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Google Agents-CLI
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://developers.googleblog.com/agents-cli-in-agent-platform-create-to-production-in-one-cli/" rel="noopener noreferrer"&gt;Google Blog: Agents-CLI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://google.github.io/agents-cli/" rel="noopener noreferrer"&gt;Google Agents-CLI Docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/google/agents-cli" rel="noopener noreferrer"&gt;Google Agents-CLI on GitHub&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Dazbo Agent Skills
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/derailed-dash/dazbo-agent-skills" rel="noopener noreferrer"&gt;Dazbo Agent Skills on GitHub&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Google Skills
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/google/skills" rel="noopener noreferrer"&gt;https://github.com/google/skills&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Genmedia
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/GoogleCloudPlatform/vertex-ai-creative-studio/tree/main/experiments/mcp-genmedia" rel="noopener noreferrer"&gt;MCP Genmedia (with AVTool)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/GoogleCloudPlatform/vertex-ai-creative-studio/tree/main/experiments/mcp-genmedia/skills" rel="noopener noreferrer"&gt;Google Genmedia Skills&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Miscellaneous
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dazbo.co.uk/" rel="noopener noreferrer"&gt;Dazbo’s Homepage&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/@derailed.dash/my-incredible-google-cloud-next-26-experience-as-a-gde-1bd291cc3696" rel="noopener noreferrer"&gt;My Incredible Google Cloud Next 26 Experience as a GDE&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>agentskills</category>
      <category>genmedia</category>
      <category>googleantigravity</category>
      <category>agentscli</category>
    </item>
  </channel>
</rss>
