<?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>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%2Cformat=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%2Cformat=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%2Cformat=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%2Cformat=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%2Cformat=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%2Cformat=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%2Cformat=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%2Cformat=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"&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"&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"&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%2Cformat=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%2Cformat=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"&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"&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"&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>
    <item>
      <title>Resolving WSL Friction with Google Antigravity: the Agy 2.0 and Agy IDE Edition</title>
      <dc:creator>Darren "Dazbo" Lester</dc:creator>
      <pubDate>Fri, 12 Jun 2026 02:42:21 +0000</pubDate>
      <link>https://dev.to/gde/resolving-wsl-friction-with-google-antigravity-the-agy-20-and-agy-ide-edition-59im</link>
      <guid>https://dev.to/gde/resolving-wsl-friction-with-google-antigravity-the-agy-20-and-agy-ide-edition-59im</guid>
      <description>&lt;h2&gt;
  
  
  Resolving Friction
&lt;/h2&gt;

&lt;p&gt;Last year when the very cool &lt;strong&gt;Google Antigravity (Agy)&lt;/strong&gt; was first launched, there were some teething issues when working with the &lt;strong&gt;Windows Subsystem for Linux (WSL)&lt;/strong&gt; environment. These caused some friction, but they could all be solved. So I wrote a &lt;a href="https://medium.com/google-cloud/working-with-google-antigravity-in-wsl-944c96c949f3" rel="noopener noreferrer"&gt;blog to consolidate the fixes&lt;/a&gt;. This blog turned out to be very popular, with about &lt;strong&gt;40,000 of you&lt;/strong&gt; having read it in the last six months!&lt;/p&gt;

&lt;h2&gt;
  
  
  Enter the New Agy 2.0 Ecosystem
&lt;/h2&gt;

&lt;p&gt;In May 2026, Google dropped the new Antigravity suite. This was a major overhaul of Antigravity, and a split into these four products:&lt;/p&gt;

&lt;ol&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 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;/ol&gt;

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

&lt;p&gt;Surprise: this introduces some &lt;em&gt;new friction&lt;/em&gt; with WSL. But good news: once again, these friction areas are easily resolved!&lt;/p&gt;

&lt;p&gt;Here I’ll list some of the problems I’ve encountered with Agy in WSL, and how to fix them.&lt;/p&gt;

&lt;h2&gt;
  
  
  No Way To Execute or Approve Interactive Commands
&lt;/h2&gt;

&lt;p&gt;This one was causing me a lot of strife: when the agent was executing shell commands in my WSL environment, it would often:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Start running the shell command.&lt;/li&gt;
&lt;li&gt;Show in the conversation window that it’s waiting for approval, but &lt;em&gt;never actually ask for it&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Move the command to a background thread.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Never complete the command&lt;/strong&gt;. Or alternatively, complete the command and not notice it has done so.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It’s easy to reproduce. In Agy IDE, whilst connected to WSL, I can issue a prompt like this:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;“Try running some interactive shell commands”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;And this is what happens:&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%2Fj2u68s4s14ea1dd0u1tq.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%2Fj2u68s4s14ea1dd0u1tq.png" alt="Agy is stuck waiting for the command to complete" width="800" height="749"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here’s the interesting thing: it says it’s &lt;strong&gt;waiting for approval&lt;/strong&gt; , but there’s actually no prompt from Agy and &lt;strong&gt;no way to provide it.&lt;/strong&gt; If you click on the first blue dot you’ll see 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.amazonaws.com%2Fuploads%2Farticles%2Fffxt6s767y4su152dagv.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%2Fffxt6s767y4su152dagv.png" alt="Interactive command" width="800" height="110"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We see the interactive command. But there’s no way to interact with it! The dropdown arrow at the bottom right simply hides this line. All we can do is terminate the background command by pressing the X.&lt;/p&gt;

&lt;p&gt;I found a LOT of posts about this on the Internet. But &lt;a href="https://www.reddit.com/r/GeminiAI/comments/1ppik6d/fix_for_google_antigravitys_terminal_blindness_it/" rel="noopener noreferrer"&gt;this one&lt;/a&gt; is the only one that worked for me. (My own flavour of the fix is mostly built on that thread.)&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;The Cause&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;It appears that my &lt;em&gt;bash&lt;/em&gt; shell prompt includes funky characters that are polluting the prompt to the agent. In my case, this is almost certainly because I’m using &lt;a href="https://ohmybash.nntoan.com/" rel="noopener noreferrer"&gt;oh-my-bash&lt;/a&gt; shell customisation.&lt;/p&gt;

&lt;p&gt;When I say shell prompt, I mean the thing that 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.amazonaws.com%2Fuploads%2Farticles%2Fg7trcocqs1p4ie3ujsdx.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%2Fg7trcocqs1p4ie3ujsdx.png" alt="Shell prompt" width="800" height="145"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Or 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.amazonaws.com%2Fuploads%2Farticles%2Fppcbarrhj6k0q7pd7j7f.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%2Fppcbarrhj6k0q7pd7j7f.png" alt="Another shell prompt" width="798" height="182"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Furthermore, my &lt;em&gt;oh-my-bash&lt;/em&gt; is actually configured to pick a random prompt from a list. This explains another thing that was confusing me: &lt;em&gt;sometimes,&lt;/em&gt; my Agy agent was able to run these shell commands. But &lt;em&gt;most of the time&lt;/em&gt; it couldn’t.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;The Fix&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Modify your &lt;code&gt;~/.bashrc&lt;/code&gt; so that it doesn’t load any funky shell prompts or other interactive prompt intelligence. Add the “Antigravity Agent fix” block in your &lt;code&gt;~/.bashrc&lt;/code&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;&lt;span class="c"&gt;### TOP OF .bashrc&lt;/span&gt;

&lt;span class="c"&gt;# Enable the subsequent settings only in interactive sessions&lt;/span&gt;
&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nv"&gt;$-&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt;
  &lt;span class="k"&gt;*&lt;/span&gt;i&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;;;&lt;/span&gt;
    &lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;;&lt;/span&gt;
&lt;span class="k"&gt;esac&lt;/span&gt;

&lt;span class="c"&gt;# Antigravity Agent fix - clean the terminal&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt;&lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$ANTIGRAVITY_AGENT&lt;/span&gt;&lt;span class="s2"&gt;"&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;
    &lt;span class="c"&gt;# Force the shell to behave as a simple pipe&lt;/span&gt;
    &lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;TERM&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;dumb
    &lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;DEBIAN_FRONTEND&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;noninteractive

    &lt;span class="c"&gt;# Disable aliases that might wait for terminal polling&lt;/span&gt;
    &lt;span class="nb"&gt;unalias&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt;

    &lt;span class="c"&gt;# Clean prompt&lt;/span&gt;
    &lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;PS1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'$ '&lt;/span&gt;
    &lt;span class="nb"&gt;unset &lt;/span&gt;PROMPT_COMMAND

    &lt;span class="c"&gt;# exit early, without running the rest of .bashrc, e.g. bypassing oh-my-bash&lt;/span&gt;
    &lt;span class="k"&gt;return
fi&lt;/span&gt;

&lt;span class="c"&gt;# The REST of your .bashrc&lt;/span&gt;
&lt;span class="c"&gt;# E.g.&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;OSH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'/home/dazbo/.oh-my-bash'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Okay, let’s restart Agy and see if it has worked…&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%2Feb1tgbldfq9jo3ybyk0w.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%2Feb1tgbldfq9jo3ybyk0w.png" alt="Prompted to allow — good start!" width="800" height="694"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It created a script, executed it, injected interactive responses to the script, and completed!&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%2F4pfjnxrvbttquzpd1osn.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%2F4pfjnxrvbttquzpd1osn.png" alt="Interactive scripts now work" width="800" height="474"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Woop!&lt;/p&gt;

&lt;h3&gt;
  
  
  Browser Agent is Broken
&lt;/h3&gt;

&lt;p&gt;The browser agent is the thing that allows you to launch a browser from your chat, and then navigate. It can also take screenshots or even record a video of the session.&lt;/p&gt;

&lt;p&gt;But… It doesn’t work in WSL out-of-the-box, of course.&lt;/p&gt;

&lt;p&gt;I test it with a prompt like this: &lt;em&gt;“Use the browser agent to navigate dazbo.co.uk”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Agy fails, and gives me a response 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.amazonaws.com%2Fuploads%2Farticles%2Fcfu9l9hd38w39szbfjov.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%2Fcfu9l9hd38w39szbfjov.png" alt="Chrome DevTools Protocol errors" width="700" height="304"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;The Fix&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;This is super-easy to fix!&lt;/p&gt;

&lt;p&gt;We just need to enable &lt;em&gt;mirroring mode&lt;/em&gt; in our WSL config!&lt;/p&gt;

&lt;p&gt;In Windows, we just need to edit our &lt;code&gt;\.wslconfig&lt;/code&gt; file (or create it, if it doesn’t yet exist):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight batchfile"&gt;&lt;code&gt;&lt;span class="kd"&gt;notepad&lt;/span&gt; &lt;span class="nv"&gt;%userprofile%&lt;/span&gt;\.wslconfig
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Just make sure the file has this block:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="nn"&gt;[wsl2]&lt;/span&gt;
&lt;span class="py"&gt;networkingMode&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;mirrored&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then shutdown and restart WSL, from your Windows Command Prompt or Powershell:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;wsl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;--shutdown&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c"&gt;# Wait a few seconds&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;wsl&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we restart Agy, and let’s see what happens…&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/Zar98ESnqRo"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  How Does It Work?
&lt;/h3&gt;

&lt;p&gt;By default, WSL2 uses a Network Address Translation (NAT) architecture, which essentially places your Linux environment behind a virtual router on a separate network isolated from Windows. When Agy triggers its browser agent, it spins up a browser instance on Windows and attempts to talk to it via the &lt;strong&gt;Chrome DevTools Protocol (CDP)&lt;/strong&gt;. In NAT mode, that connection slams straight into a networking wall because your Linux-based Agy harness can’t seamlessly see or route traffic to Windows localhost ports (like Chrome’s default debug port 9222).&lt;/p&gt;

&lt;p&gt;Switching your networking mode to mirrored solves this. Instead of treating Linux as a detached VM on a virtual router, Windows literally &lt;em&gt;mirrors&lt;/em&gt; its exact network interfaces directly into WSL2. This completely removes the network isolation barrier. Now, localhost means the exact same thing to both Windows and Linux, allowing Agy in WSL to hook straight into Chrome's remote debugging interface on Windows with zero port-forwarding friction, and no firewall headaches.&lt;/p&gt;

&lt;h2&gt;
  
  
  That’s It
&lt;/h2&gt;

&lt;p&gt;Hope this has saved you some bother.&lt;/p&gt;

&lt;p&gt;Until next time!&lt;/p&gt;

&lt;h2&gt;
  
  
  You Know What To Do!
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Please share&lt;/strong&gt; this with anyone who you think will be interested. It might help them, and it really helps me!&lt;/li&gt;
&lt;li&gt;Please interact or &lt;strong&gt;leave a comment&lt;/strong&gt; 💬.&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://antigravity.google/" rel="noopener noreferrer"&gt;Google Antigravity&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/google-cloud/working-with-google-antigravity-in-wsl-944c96c949f3" rel="noopener noreferrer"&gt;Working with Google Antigravity in WSL&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/windows/wsl/install" rel="noopener noreferrer"&gt;WSL&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/windows/wsl/networking#mirrored-mode-networking" rel="noopener noreferrer"&gt;WSL Mirrored Networking&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dazbo.co.uk" rel="noopener noreferrer"&gt;Dazbo’s Portfolio / Blogs / Applications&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>wsl</category>
      <category>agenticai</category>
      <category>browseragent</category>
      <category>googleantigravity</category>
    </item>
    <item>
      <title>Dialling Our Agents to 11: My Favourite MCP Servers</title>
      <dc:creator>Darren "Dazbo" Lester</dc:creator>
      <pubDate>Mon, 08 Jun 2026 02:27:01 +0000</pubDate>
      <link>https://dev.to/gde/dialling-our-agents-to-11-my-favourite-mcp-servers-3hbm</link>
      <guid>https://dev.to/gde/dialling-our-agents-to-11-my-favourite-mcp-servers-3hbm</guid>
      <description>&lt;h2&gt;
  
  
  What This Article Is About
&lt;/h2&gt;

&lt;p&gt;I’d like to tell you about a few of the MCP servers and agent skills that I use most often. I’ll tell you what they do, how I use them, and how to install them.&lt;/p&gt;

&lt;p&gt;These make up much of my agentic environment — or &lt;em&gt;agent harness&lt;/em&gt; — that ensures that my agentic tools do what I need them to do, in a reliable and repeatable way. Since I mostly work within the Google ecosystem, it will be no surprise to the majority of my readers that most of these (but not all) are Google-centric.&lt;/p&gt;

&lt;p&gt;This first part will cover the MCP servers, and I’ll share my favourite agent skills in the second part.&lt;/p&gt;

&lt;h2&gt;
  
  
  Not Sure What MCP Servers and Skills Are?
&lt;/h2&gt;

&lt;p&gt;Check out this video, where I explain MCP and skills, how they work, and how they differ.&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/tFUjc1Jx5_0"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;I talk about the use cases where skills are better than MCP servers and &lt;em&gt;vice versa,&lt;/em&gt; and I talk about the scenarios where you might want to use them together. (This is the talk I did for the Google &lt;em&gt;Build with AI&lt;/em&gt; roadshow.)&lt;/p&gt;

&lt;p&gt;MCP servers and skills are crucial for &lt;strong&gt;grounding our agents&lt;/strong&gt; and &lt;strong&gt;ensuring they do what we want them to do, in a repeatable way.&lt;/strong&gt; They make up two core components of the &lt;em&gt;agent harness&lt;/em&gt;. If you’re new to this term, then here’s the thing to know: &lt;em&gt;“If you’re not the model, you’re the harness.”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;When you’re using an agent to achieve a goal, that agent calls at least one model. But every agent also needs at least some of the following: prompts, context management, state management, tools, data for grounding, orchestration and an execution environment. These are the things that make up the harness.&lt;/p&gt;

&lt;p&gt;So, where exactly do MCP and skills fit into this scaffolding?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;MCP servers&lt;/strong&gt; let you have &lt;strong&gt;natural language conversations with tools, services and data&lt;/strong&gt;. They provide a standardised open interface that gives the agent its hands and eyes — letting it safely interact with local files, run database queries, fetch documentation, execute code, browse the web, and so on.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Skills&lt;/strong&gt; configure the &lt;strong&gt;on-demand knowledge&lt;/strong&gt; for our agents. I.e. the reusable prompts, patterns, workflows, checklists, principles and rules.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Assembling a tailored set of skills and MCP servers dials your agentic development environment straight up to 11. Suddenly, your agentic editor isn’t just suggesting code; it’s actively provisioning cloud services, auditing your SEO, checking your security protocols, and maintaining your documentation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Environment
&lt;/h2&gt;

&lt;p&gt;These days I’m doing all my development work in either &lt;a href="https://antigravity.google/product/antigravity-cli" rel="noopener noreferrer"&gt;Google Antigravity CLI&lt;/a&gt; or &lt;a href="https://antigravity.google/product/antigravity-ide" rel="noopener noreferrer"&gt;Antigravity IDE&lt;/a&gt;. (By the way, Google Antigravity is also known as &lt;em&gt;Agy&lt;/em&gt;. So I’ll be using this nickname frequently in this article.) If you want a general overview of how to set up skills and MCP servers in Agy, check out my article:&lt;/p&gt;

&lt;p&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;/p&gt;

&lt;p&gt;Okay, that’s it for the preamble. Let’s get into the list!&lt;/p&gt;

&lt;h2&gt;
  
  
  #1 — GitHub
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What It Does
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/github/github-mcp-server" rel="noopener noreferrer"&gt;This MCP server&lt;/a&gt; acts as the bridge between your agent and your GitHub repositories. It exposes a full set of tools for managing pull requests, creating issues, committing changes, and pushing them.&lt;/p&gt;

&lt;p&gt;It’s also particularly useful if you manage to get yourself in a git pickle! I have a bit of imposter syndrome when it comes to remembering certain git commands. &lt;em&gt;Is it just me?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;For example, you might say to Antigravity: &lt;em&gt;“Commit all the changes in my workspace in a new branch, and push.”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In response, Agy is going to pick an appropriate name for your branch, create it, stage and commit your changes with an appropriate commit message, and push to your remote repo.&lt;/p&gt;

&lt;p&gt;Here’s a really simple demo, where I’ve asked Agy:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;“Look up all my public github repos. Return them to me directly in this chat as a markdown table, including one line description, primary technologies used, and number of stars. List them in descending stars order.”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/yIrgfGh-hTo"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  Installation
&lt;/h3&gt;

&lt;p&gt;To install it, just add this block to your MCP configuration. (In Antigravity, it will be &lt;code&gt;~/.gemini/config/mcp_config.json&lt;/code&gt;.) The MCP server is remote, so you don’t need to install anything locally. You will need a GitHub &lt;a href="https://github.com/settings/tokens" rel="noopener noreferrer"&gt;access token&lt;/a&gt;, to allow your agent to authenticate to GitHub.&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="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="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;other&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;MCP&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;servers&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"remote-github"&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://api.githubcopilot.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;"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;"Authorization"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Bearer YOUR_GITHUB_PERSONAL_ACCESS_TOKEN"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Content-Type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"application/json"&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;
  
  
  #2 — Google Developer Knowledge
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What It Does
&lt;/h3&gt;

&lt;p&gt;This is a remote server that gives your agent the power to perform semantic search of the official Google developer documentation corpus. It covers everything from Android, Go, Flutter, Firebase, ADK, and Gemini APIs, to Google Cloud and TensorFlow.&lt;/p&gt;

&lt;p&gt;With &lt;a href="https://developers.google.com/knowledge/mcp?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;this MCP server&lt;/a&gt;, your agent knows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The latest Google services and APIs&lt;/li&gt;
&lt;li&gt;What’s deprecated and should be avoided&lt;/li&gt;
&lt;li&gt;Best practices for architecture, coding standards, and implementation&lt;/li&gt;
&lt;li&gt;How to troubleshoot common issues related to Google services&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In short… &lt;strong&gt;If you do any work with Google services, you want this MCP to be running!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Without this MCP, you’ll often get outdated information about Google services and APIs, or code generated with hallucinations that don’t actually work.&lt;/p&gt;

&lt;p&gt;Let’s give it a try…&lt;/p&gt;

&lt;p&gt;&lt;em&gt;“Using Google Developer Knowledge MCP, tell me about GKE in-place pod resize”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Our agent quickly comes back with an accurate and up-to-date 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.amazonaws.com%2Fuploads%2Farticles%2Fdgj58lm1ceyqvwlaes0a.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%2Fdgj58lm1ceyqvwlaes0a.png" alt="Using Google Developer Knowledge MCP" width="799" height="366"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Note: it’s not really &lt;em&gt;necessary&lt;/em&gt; to tell Agy which MCP server to use to do a task. But sometimes, if you have many servers with complementary capabilities, it can save your agent a bit of confusion if you tell it how you want it to fetch your information.&lt;/p&gt;

&lt;h3&gt;
  
  
  Installation
&lt;/h3&gt;

&lt;p&gt;To configure this, you’ll need to authenticate (which can be with ADC or an API key), and then add an entry like this to your MCP config:&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="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="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;other&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;MCP&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;servers&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"google-developer-knowledge"&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;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"args"&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;"-y"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"mcp-remote"&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://developerknowledge.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="s2"&gt;"--header"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"X-Goog-Api-Key: YOUR_API_KEY"&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;
  
  
  #3 — AVTool
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What It Does
&lt;/h3&gt;

&lt;p&gt;I love this one! It’s basically a wrapper around the free command line tool, &lt;code&gt;ffmpeg&lt;/code&gt;. With it you can manipulate video, images and audio with natural language commands. With prompts like…&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;em&gt;“Extract the audio from the video file video123.mp4 as mp3”&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;“Trim the first 5 seconds off the video”&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;“Convert all the gif files &amp;gt;5MB in this folder to jpg”&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;“Double the playback speed of this video”&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;“Optimise this video so it’s less than 10MB”&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s do a quick demo… I’ve put an episode of an old 1980s Dungeons and Dragons cartoon into the workspace directory. My goal is to extract just the first 10 seconds of the episode and save it as a separate video file. The original video has quite a long title, but I don’t have to be specific with Agy:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;“Take the first 10 seconds of the dungeons and dragons video, and save it as a new video.”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/mh_XKxrJleg"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;The clip generation was super fast. Agy, via the MCP server, ran this command, but we don’t need to know or care!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ffmpeg &lt;span class="nt"&gt;-y&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="s2"&gt;"dungeons &amp;amp; dragons -01- the night of no tomorrow (mummra1983).avi"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-ss&lt;/span&gt; 00:00:00 &lt;span class="nt"&gt;-t&lt;/span&gt; 10 &lt;span class="nt"&gt;-c&lt;/span&gt;:v libx264 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-c&lt;/span&gt;:a aac media-output/dungeons_and_dragons_10s.mp4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Insanely cool, right?&lt;/p&gt;

&lt;h3&gt;
  
  
  Installation
&lt;/h3&gt;

&lt;p&gt;Unlike the previous MCP servers I’ve described, this one requires that we set up some prerequisites...&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Of course, we need to have &lt;code&gt;ffmpeg&lt;/code&gt; &lt;a href="https://ffmpeg.org/download.html" rel="noopener noreferrer"&gt;installed&lt;/a&gt; locally.&lt;/li&gt;
&lt;li&gt;The tool can optionally write to a GCS bucket. For this, make sure you’ve specified a Google Cloud project and bucket you have write access to. (Authentication is done using ADC.)&lt;/li&gt;
&lt;li&gt;Install the local &lt;strong&gt;AVTool MCP&lt;/strong&gt; server. See the instructions &lt;a href="https://github.com/GoogleCloudPlatform/vertex-ai-creative-studio/tree/main/experiments/mcp-genmedia" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Finally, add your MCP configuration as usual:&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="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="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;other&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;MCP&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;servers&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"avtool"&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;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"mcp-avtool-go"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"env"&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;"MCP_SERVER_REQUEST_TIMEOUT"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"55000"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"PROJECT_ID"&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-google-project"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"GENMEDIA_BUCKET"&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-gcs-bucket"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"LOCATION"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"europe-west1"&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;
  
  
  #4 — NotebookLM
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What It Does
&lt;/h3&gt;

&lt;p&gt;Everyone knows I love &lt;a href="https://notebooklm.google.com/" rel="noopener noreferrer"&gt;NotebookLM&lt;/a&gt;! A quick recap, if you don’t know what it is…&lt;/p&gt;

&lt;p&gt;NotebookLM is a personalised AI research assistant built on top of Google’s multimodal Gemini models. It’s designed to help you understand, synthesise, and present complex information that’s scattered across all sorts of different formats. Some key tenets:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The information it synthesises is grounded strictly on only the sources you provide.&lt;/li&gt;
&lt;li&gt;It supports various formats of data, including videos, audio, Google Docs and Sheets, PDFs, images, web pages, and more.&lt;/li&gt;
&lt;li&gt;It can generate various types of output for you, including detailed reports, mind maps, audio podcasts, presentations, and even videos!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I’ve written a dedicated blog about using MCP to integrate with NotebookLM previously:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://medium.com/google-cloud/integrate-notebooklm-with-gemini-cli-google-antigravity-or-other-agents-with-mcp-cd83b575dc39" rel="noopener noreferrer"&gt;Integrate NotebookLM with Gemini CLI, Google Antigravity or Other Agents with MCP&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That blog has a number of use cases demonstrated, so I won’t repeat them here.&lt;/p&gt;

&lt;h3&gt;
  
  
  Installation
&lt;/h3&gt;

&lt;p&gt;This is another MCP server that runs locally, so there’s a few things you need to setup:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Have &lt;code&gt;uv&lt;/code&gt; installed. (Like many locally running MCP servers require.)&lt;/li&gt;
&lt;li&gt;Install the local &lt;code&gt;notebooklm-mcp-cli&lt;/code&gt;: &lt;code&gt;uv tool install notebook-mcp-cli&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now you can go ahead and add your MCP server entry:&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="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="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;other&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;MCP&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;servers&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"notebooklm-mcp"&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;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"uvx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"args"&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;"--from"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"notebooklm-mcp-cli"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"--with"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"fakeredis&amp;lt;2.20.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"notebooklm-mcp"&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;
  
  
  #5 — ADK-Docs
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What It Does
&lt;/h3&gt;

&lt;p&gt;This is very useful when developing using &lt;a href="https://adk.dev/" rel="noopener noreferrer"&gt;Google Agent Development Kit (ADK)&lt;/a&gt;. This particular MCP Server provides your agent with specific grounding documentation about ADK itself. These days, this one might be a little redundant, given that the Google Developer Knowledge MCP includes ADK documentation in its corpus. But I still find that having this MCP installed provides very targeted information when I’m building agents with ADK.&lt;/p&gt;

&lt;p&gt;It works by running a local &lt;code&gt;mcpdoc&lt;/code&gt; MCP server on your machine and pointing that server to the official ADK documentation. If you want to know a bit more about how this works, you might find this interesting:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://medium.com/google-cloud/give-your-ai-agents-deep-understanding-with-llms-txt-4f948590332b" rel="noopener noreferrer"&gt;Give Your AI Agents Deep Understanding With LLMS.txt&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Installation
&lt;/h3&gt;

&lt;p&gt;You do need to have &lt;code&gt;uv&lt;/code&gt; pre-installed, but otherwise, the only configuration you need is 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="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="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;other&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;MCP&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;servers&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"adk-docs-mcp"&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;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"uvx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"args"&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;"--from"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"mcpdoc"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"mcpdoc"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"--urls"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"AgentDevelopmentKit:https://adk.dev/llms.txt"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"--transport"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"stdio"&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;
  
  
  #6 — Stitch
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What It Does
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://stitch.withgoogle.com/" rel="noopener noreferrer"&gt;Google Stitch&lt;/a&gt; is very cool! &lt;strong&gt;It’s all about designing the UI.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is its tagline:&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%2Ftb1y1169qqeipidi660g.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%2Ftb1y1169qqeipidi660g.png" alt="Start with a prompt. Iterate into a design." width="757" height="317"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You describe an idea in natural language, and Stitch creates the wireframe and the interactive mockups of what your application will look like. You might give Stitch a prompt like:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;“A landing page for a movie club application. Minimalist dark-mode aesthetic with neon purple and green accents. Top bar navigation, with main window widgets for calendar and movie management.”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Let’s give that prompt a go!&lt;/p&gt;

&lt;p&gt;Initially, as Stitch is building the design, we see 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.amazonaws.com%2Fuploads%2Farticles%2F4i48hin1rqfm6qmz4pv4.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%2F4i48hin1rqfm6qmz4pv4.png" alt="Stitch — responding to my prompt" width="800" height="557"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And a minute later, we have 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.amazonaws.com%2Fuploads%2Farticles%2Fhh1px2jsr8iqjos6q50u.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%2Fhh1px2jsr8iqjos6q50u.png" alt="Movie club mockup — ready to go!" width="800" height="561"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;How cool is that?&lt;/p&gt;

&lt;p&gt;From here, you can annotate, modify and iterate.&lt;/p&gt;

&lt;p&gt;As you go, Stitch maintains your UI design in a standardised &lt;code&gt;DESIGN.md&lt;/code&gt; document that is both human and agent-readable. And you can export everything created by Stitch — the &lt;code&gt;DESIGN.md&lt;/code&gt;, the HTML, and the images — in various formats, including Figma, as a zip file, or directly into &lt;a href="https://aistudio.google.com/prompts/new_chat" rel="noopener noreferrer"&gt;AI Studio&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If I download the zip, 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.amazonaws.com%2Fuploads%2Farticles%2Fcu2stur3setyccnhjmzx.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%2Fcu2stur3setyccnhjmzx.png" alt="Zip downloaded from stitch" width="546" height="213"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now I can add these files to my development project. If I’m vibing the frontend, I could drop in these files and then ask Agy to (say) create a React web application that matches these files.&lt;/p&gt;

&lt;p&gt;But with the Stitch MCP server, it’s even easier! It essentially opens a two-way conversation about your agentic development environment (like the Agy IDE) and Stitch. So now you could say, from Agy:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;“Using Stitch MCP, create a landing page for a movie club application. Minimalist dark-mode aesthetic with neon purple and green accents. Top bar navigation, with main window widgets for calendar and movie management. Let me give it the once over before we build the actual web UI application.”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This is what we then see in Agy:&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%2F9fnvxhjq73xz53hdp18b.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%2F9fnvxhjq73xz53hdp18b.png" alt="Using Stitch MCP from Agy IDE" width="800" height="445"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then, as with any MCP server, Agy asks if it has permission to execute the required tool:&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%2Fq3flb31i4ufbvty30a8f.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%2Fq3flb31i4ufbvty30a8f.png" alt="Permission to use Stitch MCP tools" width="546" height="222"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once Agy is finished, we see 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.amazonaws.com%2Fuploads%2Farticles%2Fncdzoa54klvy6f6qw1ey.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%2Fncdzoa54klvy6f6qw1ey.png" alt="Building a design in Stitch from the Agy IDE" width="542" height="668"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Of course, we can always go into the Stitch UI and take a look at what was created.&lt;/p&gt;

&lt;p&gt;To conclude, with the Stitch MCP server we can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create the design using a natural language prompt&lt;/li&gt;
&lt;li&gt;Iterate on the design&lt;/li&gt;
&lt;li&gt;Then proceed directly to implementation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And all without ever leaving our IDE’s chat interface. Also, we never have to export any files from Stitch and dump them into our workspace. We have true two-way conversation between our Agy agent and Stitch.&lt;/p&gt;

&lt;h3&gt;
  
  
  Installation
&lt;/h3&gt;

&lt;p&gt;Stitch uses a remote MCP server, so we just need to download an API key from Stitch, and then add this to our MCP config:&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="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="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;other&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;MCP&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;servers&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"StitchMCP"&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;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"args"&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;"-y"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"mcp-remote"&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://stitch.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="s2"&gt;"--header"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"X-Goog-Api-Key: YOUR_API_KEY"&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 Cloud Remote MCP Servers, e.g. Firestore, BigQuery, etc
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What It Does
&lt;/h3&gt;

&lt;p&gt;These have been around for a little while now, but Google made them generally available (GA) in April 2026.&lt;/p&gt;

&lt;p&gt;Basically, they are a &lt;a href="https://docs.cloud.google.com/mcp/supported-products" rel="noopener noreferrer"&gt;set of remote MCP servers&lt;/a&gt;, hosted and fully-managed by Google. They align to many of Google’s services and products, like BigQuery, Firestore, Cloud SQL, Cloud Storage, Cloud Run, GKE, Maps, Cloud Monitoring, Cloud Logging, and so on. &lt;strong&gt;They allow us to have natural language conversations with these Google services&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;And because they are fully-managed, we don’t have to install anything and we never have to maintain them.&lt;/p&gt;

&lt;p&gt;Typically, I don’t have these enabled all the time. But if I’m working with a particular Google Cloud service for a given project, I’ll typically configure the required MCP server for as long as I need it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Installation
&lt;/h3&gt;

&lt;p&gt;We do need to do a couple of things in Google Cloud first. This includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ensuring we have a Google project&lt;/li&gt;
&lt;li&gt;Enabling the API for the service we want to talk to, e.g. &lt;code&gt;bigquery.googleapis.com&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Enabling the required MCP server&lt;/li&gt;
&lt;li&gt;Granting your identity the &lt;code&gt;roles/mcp.toolUser&lt;/code&gt; role&lt;/li&gt;
&lt;li&gt;Granting your identity the correct IAM role to use the underlying service that is provided via MCP&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then we can add our MCP configuration:&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="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="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;other&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;MCP&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;servers&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"FirestoreMCP"&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://firestore.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/cloud-platform"&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_PROJECT_ID"&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;If you want to know more about these Google MCP servers, check out &lt;a href="https://medium.com/u/802a4d428d95" rel="noopener noreferrer"&gt;Romin Irani&lt;/a&gt;’s &lt;a href="https://medium.com/google-cloud/google-mcp-servers-tutorial-series-3f48dd21e99f" rel="noopener noreferrer"&gt;Google MCP Server Tutorial Series&lt;/a&gt;. He goes into a lot of depth, and provides a bunch of use cases.&lt;/p&gt;

&lt;h2&gt;
  
  
  #8 — gcloud
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What It Does
&lt;/h3&gt;

&lt;p&gt;This empowers our agent to know how to use the Google &lt;code&gt;gcloud&lt;/code&gt; CLI. So we can issue natural language prompts like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;em&gt;“Find all log entries with severity ERROR in the last 15 minutes”&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;“Deploy my local container to Cloud Run and split the traffic 50/50”&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This saves a lot of time in trying to determine the exact &lt;code&gt;gcloud&lt;/code&gt; syntax to do a specific thing.&lt;/p&gt;

&lt;h3&gt;
  
  
  Installation
&lt;/h3&gt;

&lt;p&gt;This is a remote MCP server, and setting it up is as simple as adding this config:&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="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="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;other&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;MCP&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;servers&lt;/span&gt;&lt;span class="w"&gt;  
  &lt;/span&gt;&lt;span class="nl"&gt;"gcloud"&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;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"args"&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;"-y"&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-cloud/gcloud-mcp"&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;It operates with the authority of your ADC credentials.&lt;/p&gt;

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

&lt;p&gt;Having a robust agent harness transforms the effectiveness of your agent. Having a good set of MCP servers is part of this harness. Give these a try in your own development environment, whether it’s Antigravity or other. And let me know: which are your favourites? What other MCP servers would you recommend?&lt;/p&gt;

&lt;p&gt;Stay tuned. The Agent Skills rundown will arrive soon.&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;ul&gt;
&lt;li&gt;Skills and MCP Servers Explained (Build with AI, Prishtina)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/tFUjc1Jx5_0"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;ul&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://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://github.com/github/github-mcp-server" rel="noopener noreferrer"&gt;GitHub Remote MCP Server&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;Google Developer Knowledge MCP server&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" rel="noopener noreferrer"&gt;MCP Genmedia (with AVTool)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://notebooklm.google.com/" rel="noopener noreferrer"&gt;NotebookLM&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/google-cloud/integrate-notebooklm-with-gemini-cli-google-antigravity-or-other-agents-with-mcp-cd83b575dc39" rel="noopener noreferrer"&gt;Integrate NotebookLM with Gemini CLI, Google Antigravity or Other Agents with MCP&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/jacob-bd/notebooklm-mcp-cli" rel="noopener noreferrer"&gt;NotebookLM-MCP-CLI&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;li&gt;&lt;a href="https://stitch.withgoogle.com/?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;Google Stitch&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/google-cloud/google-mcp-servers-tutorial-series-3f48dd21e99f" rel="noopener noreferrer"&gt;Google MCP Servers Tutorial Series&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/googleapis/gcloud-mcp" rel="noopener noreferrer"&gt;Gcloud CLI MCP&lt;/a&gt;&lt;/li&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;/ul&gt;

</description>
      <category>mcpserver</category>
      <category>agenticai</category>
      <category>googleantigravity</category>
      <category>agentharness</category>
    </item>
    <item>
      <title>Configuring MCP Servers and Skills for Antigravity CLI and IDE</title>
      <dc:creator>Darren "Dazbo" Lester</dc:creator>
      <pubDate>Sun, 24 May 2026 10:36:37 +0000</pubDate>
      <link>https://dev.to/gde/configuring-mcp-servers-and-skills-for-antigravity-cli-and-ide-2bh0</link>
      <guid>https://dev.to/gde/configuring-mcp-servers-and-skills-for-antigravity-cli-and-ide-2bh0</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;We had a few big announcements from Google I/O 2026 in the AI space. One was the announcement of Gemini Flash 3.5, which went straight to general availability (GA). Another was the launch of the &lt;strong&gt;Google Antigravity (aka “Agy”) ecosystem&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.amazonaws.com%2Fuploads%2Farticles%2F6uhqlojdem5pub0ikscy.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%2F6uhqlojdem5pub0ikscy.png" alt="Antigravity Suite" width="800" height="437"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Agy suite supports and enables Gemini 3.5 from day 1 and is made up of a number of products:&lt;/p&gt;

&lt;ol&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.&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.&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 — somewhat controversially — replaces the hugely popular and open-source 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;/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%2Fd86va7lflgp7i6ygqdik.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%2Fd86va7lflgp7i6ygqdik.png" alt="Gemini CLI becomes Antigravity CLI" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I can understand Google’s rationale for bringing Gemini CLI into the Antigravity suite. Previously these products were developed independently and in parallel. As a result they had different standards and approaches for configuration (such as MCP servers), and where to put things… like skills. This creates a certain amount of friction for users. Now, in theory, we only need to configure in one place.&lt;/p&gt;

&lt;p&gt;There’s already a bunch of articles in the Google Cloud Publication describing how to get started with the Antigravity suite.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Here I’m going to briefly share my experience in configuring MCP servers and skills.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is literally day 1 of me experimenting with these things in Agy, so there’s a lot I need to discover. And I expect we’ll continue to see a lot of bug fixes across the Agy suite too. But I wanted to share this with you ASAP, as I’ve been getting a lot of folks asking me questions about this. I hope it’s useful for you.&lt;/p&gt;

&lt;h2&gt;
  
  
  Global Configuration
&lt;/h2&gt;

&lt;p&gt;As before, we have a &lt;code&gt;.gemini&lt;/code&gt; folder in our home directory. But now it looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.gemini
├── antigravity/
├── config/
│   ├── plugins/ # Global / shared plugins
│   ├── projects/ # Approved project folders
│   └── mcp_config.json # Global / shared MCP config
├── antigravity-cli/
│   ├── mcp/ # Dynamically generated from shared MCP config
│   └── settings.json # CLI settings
├── antigravity-ide/
│   ├── mcp/ # Dynamically generated from shared MCP config
│   ├── plugins/ # Symlinked from global config
│   └── installation_id
├── skills/ # Global / shared skills
│   └── {skill_name}/
│       └── SKILL.md
└── GEMINI.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Some things to note about this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;At the time of writing, the official Antigravity documentation says that &lt;strong&gt;to configure skills “globally”&lt;/strong&gt; , you need to put them here: &lt;code&gt;~/.gemini/antigravity/skills/&amp;lt;skill-folder&amp;gt;/&lt;/code&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%2Fe1ehc3hxehz2d6i1626l.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%2Fe1ehc3hxehz2d6i1626l.png" alt="Where Skills Live — According to the documentation" width="742" height="222"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;But my experience is that &lt;strong&gt;&lt;em&gt;this is incorrect&lt;/em&gt;&lt;/strong&gt;. Antigravity tools do not pick up skills placed in this location. Instead, you should put your skills folder at the top of your &lt;code&gt;.gemini&lt;/code&gt; folder. We can confirm this by running the &lt;code&gt;/skills&lt;/code&gt; command from inside Agy 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.amazonaws.com%2Fuploads%2Farticles%2F4q1fye9kxqytods7uyv6.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%2F4q1fye9kxqytods7uyv6.png" alt="/skills" width="800" height="314"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You can see that “global” skills — meaning those available to all workspaces when running &lt;em&gt;Agy CLI only&lt;/em&gt; — should go in &lt;code&gt;~/.gemini/antigravity-cli/skills&lt;/code&gt;, whereas &lt;strong&gt;“shared” skills&lt;/strong&gt; — meaning those available to *&lt;em&gt;all workspaces running &lt;em&gt;any&lt;/em&gt; Antigravity tools *&lt;/em&gt; — should go in &lt;code&gt;~/.gemini/skills&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;If we want to share &lt;strong&gt;MCP server configurations&lt;/strong&gt; across Antigravity tools, you need to create &lt;code&gt;mcp_config.json&lt;/code&gt; file and place it in the new &lt;code&gt;~/.gemini/config&lt;/code&gt; folder. (This is where “shared” extensions — now called “plugins” go also.)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  MCP Configuration
&lt;/h3&gt;

&lt;p&gt;Here’s what my new &lt;code&gt;~/.gemini/config/mcp_config.json&lt;/code&gt; currently looks like:&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;"lyria"&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;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"mcp-lyria-go"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"env"&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;"MCP_SERVER_REQUEST_TIMEOUT"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"55000"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"GENMEDIA_BUCKET"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"my-bucket-name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"PROJECT_ID"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"my-google-project"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"LOCATION"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"europe-west1"&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;"disabled"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&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;"avtool"&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;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"mcp-avtool-go"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"env"&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;"MCP_SERVER_REQUEST_TIMEOUT"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"55000"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"PROJECT_ID"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"my-google-project"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"GENMEDIA_BUCKET"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"my-bucket-name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"LOCATION"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"europe-west1"&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;"chirp3-hd"&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;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"mcp-chirp3-go"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"env"&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;"MCP_SERVER_REQUEST_TIMEOUT"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"55000"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"GENMEDIA_BUCKET"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"my-bucket-name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"PROJECT_ID"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"my-google-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="nl"&gt;"gcloud"&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;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"args"&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;"-y"&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-cloud/gcloud-mcp"&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;"notebooklm-mcp"&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;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"uvx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"args"&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;"--from"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"notebooklm-mcp-cli"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"--with"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"fakeredis&amp;lt;2.20.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"notebooklm-mcp"&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;"disabled"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&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;"StitchMCP"&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;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"args"&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;"-y"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"mcp-remote"&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://stitch.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="s2"&gt;"--header"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"X-Goog-Api-Key: &amp;lt;my-stitch-api-key&amp;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;"env"&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;"FirestoreMCP"&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://firestore.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/cloud-platform"&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;"dazbo-portfolio"&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;"disabled"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&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;"remote-github"&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://api.githubcopilot.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;"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;"Authorization"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Bearer &amp;lt;my-github-api-key&amp;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;"Content-Type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"application/json"&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;"google-developer-knowledge"&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;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"args"&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;"-y"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"mcp-remote"&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://developerknowledge.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="s2"&gt;"--header"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"X-Goog-Api-Key: &amp;lt;my-google-developer-knowledge-api-key&amp;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;"env"&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;"google-cloud-resource-manager"&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://cloudresourcemanager.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="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 notes about this MCP JSON file…&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You need to use &lt;code&gt;serverUrl&lt;/code&gt;, not the older &lt;code&gt;httpUrl&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;The “timeout” parameter is no longer supported at the top level of each MCP server.&lt;/li&gt;
&lt;li&gt;Inline comments are not supported.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s see if this works…&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%2F72h5sraemq3iqdofjdod.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%2F72h5sraemq3iqdofjdod.png" alt="MCP servers picked up and working in Agy CLI" width="799" height="249"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let’s test one of these.&lt;/p&gt;

&lt;p&gt;I say to Agy CLI: “&lt;em&gt;List my public GitHub repos. Present them in a markdown table, along with their summaries, primary technologies, and number of stars. List in desc stars order.”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;And Agy CL comes back with:&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%2Fydbhyl8758aclhx8pz4o.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%2Fydbhyl8758aclhx8pz4o.png" alt="GitHub MCP Server testing" width="800" height="344"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So that worked fine.&lt;/p&gt;

&lt;p&gt;But what about in Agy IDE? Let’s just ask the agent, &lt;em&gt;“What MCP servers do we have?”&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.amazonaws.com%2Fuploads%2Farticles%2F9j0c6x2p550zbjimz4ts.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%2F9j0c6x2p550zbjimz4ts.png" alt="MCP Servers picked up in Agy IDE" width="800" height="577"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So you can see that Agy IDE has picked up the same MCP configuration. Hurrah!&lt;/p&gt;

&lt;p&gt;I did discover one issue… In my old Gemini CLI MCP server configurations, I was able to pass in environment variables, e.g. for API keys. In Agy CLI / IDE, this isn’t working for me and I’ve had to hard-code these keys into my &lt;code&gt;mcp_config.json&lt;/code&gt; file. I hope this will get fixed soon.&lt;/p&gt;

&lt;h3&gt;
  
  
  Skills Configuration
&lt;/h3&gt;

&lt;p&gt;I started by downloading and installing a number of skills in the usual way; i.e. via npx, 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="c"&gt;# Skills related&lt;/span&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

&lt;span class="c"&gt;# My skills - e.g. project-documentation&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;# Agentic dev, Gemini, ADK&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/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;span class="c"&gt;# Research, content, documentation, and marketing&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; deep-research
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
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; strategy-advisor
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
npx skills add https://github.com/wshobson/agents &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; architecture-decision-records
npx skills add https://github.com/coreyhaines31/marketingskills &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; seo-audit

&lt;span class="c"&gt;# UI and frontend&lt;/span&gt;
npx skills add https://github.com/vercel-labs/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; vercel-react-best-practices
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;p&gt;These commands install skills to your &lt;code&gt;~/.agents/skills&lt;/code&gt; folder. But I want them to be in &lt;code&gt;~/.gemini/skills&lt;/code&gt;. As mentioned previously, this location is picked up by all Agy products. So, go ahead and move the skills you’ve installed. Or you can run a script like this to do it for 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="k"&gt;for &lt;/span&gt;d &lt;span class="k"&gt;in&lt;/span&gt; ~/.agents/skills/&lt;span class="k"&gt;*&lt;/span&gt;/&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="k"&gt;do&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;"&lt;/span&gt;&lt;span class="nv"&gt;$d&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/.gemini/skills/&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;basename&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$d&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;mv&lt;/span&gt; ~/.agents/skills/&lt;span class="k"&gt;*&lt;/span&gt; ~/.gemini/skills/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By the way, I’ve actually created a skill that does this for me. I.e. it helps with installing any skill, and then relocating it to the appropriate location for Antigravity. It’s called &lt;code&gt;deploy-skills-in-antigravity&lt;/code&gt; and you can check it out &lt;a href="https://github.com/derailed-dash/dazbo-agent-skills" rel="noopener noreferrer"&gt;here&lt;/a&gt;. After installing it, I can say to Agy:&lt;/p&gt;

&lt;p&gt;“please install the skill seo-audit from &lt;a href="https://github.com/coreyhaines31/marketingskills" rel="noopener noreferrer"&gt;https://github.com/coreyhaines31/marketingskills&lt;/a&gt;”&lt;/p&gt;

&lt;p&gt;Agy then activates my skill and uses the correct commands to install and move the newly installed SEO skill.&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%2Fnpve9ksym1lm8nro5dtc.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%2Fnpve9ksym1lm8nro5dtc.png" alt="Using my skill to install and move other skills" width="798" height="229"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;(If you like this skill, please add a star to my repo!)&lt;/p&gt;

&lt;p&gt;When we start Agy CLI, these skills are all available. Let’s check in Agy IDE too. I ask Agy IDE: &lt;em&gt;“What skills do we have installed?”&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.amazonaws.com%2Fuploads%2Farticles%2Fxmelkydpxh2rmdlnbtyz.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%2Fxmelkydpxh2rmdlnbtyz.png" alt="Skills available in Agy IDE" width="800" height="736"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So we can see the skills are detected in Agy IDE, as required.&lt;/p&gt;

&lt;p&gt;If I ask the Agy agent to &lt;em&gt;“Perform a core documentation review,”&lt;/em&gt; we can see that it uses the required skills automatically:&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%2Frqvtwlvxnlxpd0ekmptm.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%2Frqvtwlvxnlxpd0ekmptm.png" alt="Activating skills" width="800" height="524"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;(If you’re interested in this documentation review skill, then you can obtain it &lt;a href="https://github.com/derailed-dash/dazbo-agent-skills" rel="noopener noreferrer"&gt;here&lt;/a&gt;. Please add a star to the repo, if you find it useful!)&lt;/p&gt;

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

&lt;p&gt;So, where does that leave us?&lt;/p&gt;

&lt;p&gt;Migrating from the old Gemini CLI to the new Antigravity ecosystem does require a bit of mental rewiring when it comes to folder structures. But having a single, unified source of truth for your MCP servers and skills is a leap forward. No more duplicating configurations or wondering why a custom skill works in your terminal but fails in your IDE. (Hopefully!)&lt;/p&gt;

&lt;p&gt;Is it perfect? Not yet. We still have some day-one paper cuts — like that frustrating environment variable bug in the global MCP configuration that forces us to hardcode API keys for now. But given the sheer startup speed of the new Go-based CLI and the potential of the shared agent harness, the foundation is incredibly solid.&lt;/p&gt;

&lt;p&gt;Hopefully, this guide saves you some time scratching your head over directory discrepancies. Let me know if you run into any other teething issues!&lt;/p&gt;

&lt;p&gt;Now, if you’ll excuse me, I think it’s time to put on a Hawaiian shirt, mix up a piña colada, and go enjoy a bit of sunshine.&lt;/p&gt;

&lt;p&gt;Until next time, happy building!&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;ul&gt;
&lt;li&gt;&lt;a href="http://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://developers.googleblog.com/en/an-important-update-transitioning-gemini-cli-to-antigravity-cli/?utm_campaign=DEVECO_GDEMembers&amp;amp;utm_source=deveco" rel="noopener noreferrer"&gt;An important update: Transitioning Gemini CLI to Antigravity CLI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://antigravity.google/docs/home?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://medium.com/google-cloud/antigravity-cli-tutorial-series-12b46cfe3bf2" rel="noopener noreferrer"&gt;Antigravity CLI Tutorial Series&lt;/a&gt; from &lt;a href="https://medium.com/u/802a4d428d95" rel="noopener noreferrer"&gt;Romin Irani&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="http://darrenlester.net/" rel="noopener noreferrer"&gt;My Portfolio / Blogs / Applications&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>agentskills</category>
      <category>antigravitycli</category>
      <category>gemini</category>
      <category>googleantigravity</category>
    </item>
    <item>
      <title>Upgrading Your Microsoft Surface Laptop Hard Disk — Easier Than You Think!</title>
      <dc:creator>Darren "Dazbo" Lester</dc:creator>
      <pubDate>Sat, 23 May 2026 10:59:05 +0000</pubDate>
      <link>https://dev.to/dazbo/upgrading-your-microsoft-surface-laptop-hard-disk-easier-than-you-think-3jpb</link>
      <guid>https://dev.to/dazbo/upgrading-your-microsoft-surface-laptop-hard-disk-easier-than-you-think-3jpb</guid>
      <description>&lt;h2&gt;
  
  
  Overview
&lt;/h2&gt;

&lt;p&gt;Older generations of Microsoft Surface devices were not upgradeable. You made your choice and you were stuck with the consequences. But the Microsoft Surface Laptop 7 is surprisingly easy to upgrade.&lt;/p&gt;

&lt;p&gt;Here I’ll walk you through:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What types of upgrade SSDs are compatible&lt;/li&gt;
&lt;li&gt;How to create your recovery image&lt;/li&gt;
&lt;li&gt;How to open up your case, including the screwdriver you’ll need&lt;/li&gt;
&lt;li&gt;How to use the recovery image, including some common gotchas&lt;/li&gt;
&lt;li&gt;A few handy links of bits and pieces you might want to buy&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why Would You Want to Do This?
&lt;/h2&gt;

&lt;p&gt;I love the Microsoft Surface Laptop range. I currently have a Surface Laptop 7 and I think it’s a great bit of kit. (By the way, you should check out my blog: &lt;a href="https://medium.com/@derailed.dash/should-you-switch-to-a-windows-arm-laptop-my-experience-of-the-surface-laptop-7-f43725133f24" rel="noopener noreferrer"&gt;Should You Switch to a Windows ARM Laptop? My Experience of the Surface Laptop 7&lt;/a&gt;.)&lt;/p&gt;

&lt;p&gt;But these are not cheap. They’re premium devices with premium prices. And when you buy one, you need to think carefully about the spec you’re getting. When the Surface Laptop 7 launched, here’s what the line-up looked like, and how much each model would set you back:&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
        &lt;div class="c-embed__cover"&gt;
          &lt;a href="https://docs.google.com/spreadsheets/d/e/2PACX-1vRQ47au_CTBxdLh53-viav35ih-_DzU86wUZXjqkFrv41Q8RmMObRseE9IIXdYqWW8Gyph1vCkd1cgg/pubhtml?gid=0&amp;amp;amp%3Bsingle=true" class="c-link align-middle" rel="noopener noreferrer"&gt;
            &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-us.googleusercontent.com%2Fdocs%2FAHkbwyKrSWvWJaL1h1LADsVhqIP5NeZfOaMaF3st_awIm9TpwwMrXuEdzGHNN1itjL4ylbG0VAah2YINmSxX811iW9enzfbjM2NPqkTY5IEeteIi9WXHaeTb%3Dw1200-h630-p" height="630" class="m-0" width="1200"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://docs.google.com/spreadsheets/d/e/2PACX-1vRQ47au_CTBxdLh53-viav35ih-_DzU86wUZXjqkFrv41Q8RmMObRseE9IIXdYqWW8Gyph1vCkd1cgg/pubhtml?gid=0&amp;amp;amp%3Bsingle=true" rel="noopener noreferrer" class="c-link"&gt;
            Microsoft Surface Laptop 7 - Launch Configurations and Prices - Google Drive
          &lt;/a&gt;
        &lt;/h2&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
            &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fssl.gstatic.com%2Fdocs%2Fspreadsheets%2Fspreadsheets-2026-v2.ico" width="256" height="256"&gt;
          docs.google.com
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;But what do you do if you’ve already bought it, and now your disk is full?&lt;/strong&gt; My laptop has a 512GB and it’s full. No amount of housekeeping is going to save me!&lt;/p&gt;

&lt;p&gt;And what if you wanted to put in a 2TB disk? There’s no option for that.&lt;/p&gt;

&lt;h2&gt;
  
  
  Upgrade Walkthrough
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Ordering Parts
&lt;/h3&gt;

&lt;p&gt;First you’re going to need your &lt;strong&gt;replacement SSD&lt;/strong&gt;. The internal drive on the Surface Laptop 7 is a M.2 SSD. But it’s not the standard 80mm card. For this laptop you need the shorter 30mm format, called “ &lt;strong&gt;2230&lt;/strong&gt; ”. Then pick your size. I wanted to upgrade my 512GB to 1TB.&lt;/p&gt;

&lt;p&gt;There are a few popular choices for this SSD upgrade, including the Corsair MP600 Micro, the WD Black SN770M, and the Sabrent Rocket 2230. I went with the Corsair and bought one of these on Amazon:&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%2Fozj7f9d6mteh4la0zpfy.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.amazonaws.com%2Fuploads%2Farticles%2Fozj7f9d6mteh4la0zpfy.jpg" alt="Corsair MP600 Mini 1TB M.2 2230" width="800" height="620"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.amazon.co.uk/dp/B0D9MJCFNK?ref=ppx_yo2ov_dt_b_fed_asin_title&amp;amp;th=1" rel="noopener noreferrer"&gt;This model&lt;/a&gt; cost me £145.&lt;/p&gt;

&lt;p&gt;Next, you’re going to need an appropriate screwdriver to take the laptop apart. After a bit of research I determined that the screws used are “5IP”, aka Torx Plus 5. OMG, I fell down a rabbit hole of screws used in devices. Here is an &lt;a href="https://www.ifixit.com/News/110702/torx-plus-the-high-tech-screw-hiding-in-our-gadgets" rel="noopener noreferrer"&gt;excellent article&lt;/a&gt; that explains what Torx and Torx Plus screws are, and why they exist.&lt;/p&gt;

&lt;p&gt;But it turns out that getting a Torx Plus screwdriver is difficult; certainly here in the UK. But here’s the good news: a standard Torx T5 screwdriver does the job fine. You could just buy such a screwdriver on its own, but I ended up buying this very cool &lt;a href="https://www.amazon.co.uk/dp/B0D633J3C7?ref=ppx_yo2ov_dt_b_fed_asin_title&amp;amp;th=1" rel="noopener noreferrer"&gt;JOREST precision screwdriver set&lt;/a&gt; from Amazon for a tenner. It includes the T5 bit that we need.&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%2Fwcz1kkbrdqzqj7ce8o1m.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.amazonaws.com%2Fuploads%2Farticles%2Fwcz1kkbrdqzqj7ce8o1m.jpg" alt="JOREST 50-in-1 precision screwdriver set" width="800" height="830"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The other great thing about this set is that &lt;strong&gt;the screwdriver bits are magnetic, and so too is the case&lt;/strong&gt;. This is very handy, because the screws you’re working with are &lt;em&gt;TINY&lt;/em&gt;! They are easy to lose. Being able to lift them out with the screwdriver and then drop them into a magnetised case is a life-saver!&lt;/p&gt;

&lt;h3&gt;
  
  
  Create Your USB Recovery Drive
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;Time required: approx 30 mins. (Most of it spent downloading and waiting for the copy.)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You’re going to need a bootable USB recovery drive to perform a clean install of Windows 11 on your Surface Laptop after you’ve installed your shiny new SSD.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://support.microsoft.com/en-us/surface/drivers-firmware/creating-and-using-a-usb-recovery-drive-for-surface" rel="noopener noreferrer"&gt;This Microsoft guide&lt;/a&gt; explains what to do. There are some things to note:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;First, we &lt;strong&gt;download the Surface Laptop 7 factory image&lt;/strong&gt; from &lt;a href="https://support.microsoft.com/en-us/surface-recovery-image" rel="noopener noreferrer"&gt;this page&lt;/a&gt;. You’ll need to choose “Surface Laptop” from the dropdown, and enter your serial number.&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%2Fu6q57up555v4l3jlji2i.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%2Fu6q57up555v4l3jlji2i.png" alt="Select your Surface device" width="716" height="418"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I downloaded the newer “ &lt;strong&gt;Windows 11 Home Version 25H2&lt;/strong&gt; ”. It turns out that this creates a minor problem, but easy to solve. I tell you more in a minute.&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%2Fag9gtscl6fqrjzdf4xbz.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%2Fag9gtscl6fqrjzdf4xbz.png" alt="Download the Surface recovery image" width="780" height="555"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Next we need to &lt;strong&gt;create a USB recovery drive&lt;/strong&gt;. First we create the recovery drive from Windows, and then we’ll transfer the factory image files to it. The documentation is ambiguous about the size of flash drive you can use. The MS guide says &lt;em&gt;“32GB is large enough but you may be able to use a smaller size”&lt;/em&gt;. And I’ve found other blogs and advice online that says it won’t work if your drive is bigger than 32GB. This is incorrect; you can go larger. I used a 128GB and it was fine. Basically, the “&lt;a href="https://support.microsoft.com/en-us/surface/drivers-firmware/creating-and-using-a-usb-recovery-drive-for-surface#bkmk_create11" rel="noopener noreferrer"&gt;Create a recovery drive&lt;/a&gt;” option in Windows will format your USB drive with a 32GB FAT32 partition. (By the way, you can run this step from any machine running Windows 11. It doesn’t have to be done on your Surface Laptop.)&lt;/li&gt;
&lt;li&gt;Now, unzip the recovery image you downloaded previously, and then copy all folders and files directly to your recovery drive. The file transfer took me about 10 minutes. (You should definitely unzip first. It’s much faster if you do this, rather than just opening the zip and then copying over all the contents.) When prompted, select &lt;em&gt;“Replace the files in the destination.”&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Swap the SSD
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;Time required: 5 minutes.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;First we need to take off the back plate. Ensure the device is powered off and disconnected from power. Then remove the four black rubber stoppers from the laptop to expose the screws we need to remove. The screwdriver kit I mentioned earlier comes with a handy tool that’s great for removing these stoppers.&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%2Fpzd9mmj6wgqbabb4gx1x.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.amazonaws.com%2Fuploads%2Farticles%2Fpzd9mmj6wgqbabb4gx1x.jpeg" alt="Remove the rubber feet" width="800" height="520"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now we need to remove the screws themselves. This is what a Torx Plus 5 screw looks like, up close and personal!&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%2Fbhm5l315i2c5onvgf9me.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.amazonaws.com%2Fuploads%2Farticles%2Fbhm5l315i2c5onvgf9me.jpeg" alt="Torx Plus 5 screw" width="800" height="602"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can go ahead and use our Torx T5 screwdriver bit. Be careful. Since this isn’t the perfect fitting screwdriver, you don’t want to damage the screw heads.&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%2Fbclwya2ukw0c9sum36ev.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.amazonaws.com%2Fuploads%2Farticles%2Fbclwya2ukw0c9sum36ev.jpeg" alt="Removing the Torx screws" width="800" height="963"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One all four screws are removed, we just need to remove the back plate. Again, we can use the plastic tool from our screwdriver set to do this. It comes off incredibly easy.&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%2Fh16lotbvb06ag7kf8f1h.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.amazonaws.com%2Fuploads%2Farticles%2Fh16lotbvb06ag7kf8f1h.jpeg" alt="Lift off the back plate" width="800" height="635"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And now we can see the SSD:&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%2Fibbxpptaas2ujjho5r1k.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%2Fibbxpptaas2ujjho5r1k.png" alt="Here's the SSD" width="800" height="602"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You need to unscrew it with the same Torx T5 screwdriver. And unpeel the tape that is holding it in place. Then remove, and insert your new SSD. Screw it down and put the tape back in place.&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%2Fghr5j399d3v37a89oqj1.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.amazonaws.com%2Fuploads%2Farticles%2Fghr5j399d3v37a89oqj1.jpeg" alt="Inserting the replacement SSD" width="800" height="554"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now go ahead and reattach the back plate. When you’re putting the screws back in, don’t over-tighten. Again, we want to be careful not to damage the screw heads.&lt;/p&gt;

&lt;h3&gt;
  
  
  Booting From the Recovery Drive
&lt;/h3&gt;

&lt;p&gt;Insert the recovery drive into the USB port, and attach power to the laptop. Then go ahead and start the device.&lt;/p&gt;

&lt;p&gt;After a few seconds, you might see the error &lt;em&gt;“Couldn’t find a bootable operating system. Check the Boot configuration to try to fix this.”&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.amazonaws.com%2Fuploads%2Farticles%2F9lv1mh24zis7ynaga4cf.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.amazonaws.com%2Fuploads%2Farticles%2F9lv1mh24zis7ynaga4cf.jpeg" alt="Boot error" width="800" height="513"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Eek! We don’t want to see that. But panic not! The issue here is the laptop is set to use Secure Boot in the UEFI, but the Windows 11 factory recovery image is signed with a newer certificate that isn’t recognised by the device!&lt;/p&gt;

&lt;p&gt;This is easy to fix. When you press “Ok” on the error, you’ll see the UEFI settings. From here select “Security”, then under “Secure Boot” select “Change configuration”. Now select disable secure boot. (Don’t worry; we’ll revert this later.)&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%2Ffnl6u1lpy27xdwobw0fc.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.amazonaws.com%2Fuploads%2Farticles%2Ffnl6u1lpy27xdwobw0fc.jpeg" alt="Disabling secure boot" width="800" height="570"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now your laptop will restart and it should detect your recovery drive. By the way, you’ll see a big red banner with an unlocked padlock as it boots. This is to remind you that Secure Boot is disabled.&lt;/p&gt;

&lt;p&gt;You’ll now be prompted how you want to recover. Select &lt;em&gt;“Just remove my files”&lt;/em&gt;, and the recovery process will begin. At this point, you’re into a fairly standard Windows install flow.&lt;/p&gt;

&lt;h3&gt;
  
  
  Re-Enable Secure Boot
&lt;/h3&gt;

&lt;p&gt;Once Windows is installed, we have no more use for the USB recovery drive, and we can re-enable Secure Boot. To do this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Shutdown the laptop.&lt;/li&gt;
&lt;li&gt;Press and hold the volume-up button and then press the power button.&lt;/li&gt;
&lt;li&gt;Once the MS logo appears, you can release the volume-up button.&lt;/li&gt;
&lt;li&gt;The UEFI screen will appear and you can re-enable Secure Boot in the Security menu.&lt;/li&gt;
&lt;/ol&gt;

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

&lt;p&gt;And there you have it! For around £150 and less than an hour of actual desk time, my Surface Laptop 7 has gone from a cramped 512GB base model to a spacious 1TB powerhouse — saving me a massive chunk of cash compared to buying a higher-tier spec directly from Microsoft.&lt;/p&gt;

&lt;p&gt;The ability to easily upgrade the internals using a M.2 2230 slot is a massive win for repairability and longevity in the thin-and-light laptop space, and Microsoft deserves real credit for making this generation so incredibly accessible to work on. If you’ve been sitting on the fence wondering if you should pull the trigger on upgrading your own storage, stop hesitating. Grab yourself a solid 2230 drive, a decent precision bit set, and go for it!&lt;/p&gt;

&lt;h2&gt;
  
  
  You Know What To Do!
&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
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.amazon.co.uk/dp/B0D9MJCFNK?ref=ppx_yo2ov_dt_b_fed_asin_title&amp;amp;th=1" rel="noopener noreferrer"&gt;Corsair MP600 Mini 1TB M.2 2230 SSD — Amazon&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.amazon.co.uk/dp/B0D633J3C7?ref=ppx_yo2ov_dt_b_fed_asin_title&amp;amp;th=1" rel="noopener noreferrer"&gt;JOREST 50-in-1 Precision Screwdriver Set — Amazon&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.ifixit.com/News/110702/torx-plus-the-high-tech-screw-hiding-in-our-gadgets" rel="noopener noreferrer"&gt;Torx Plus: High-Tech Screws Hiding in our Gadgets&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.microsoft.com/en-us/surface/drivers-firmware/creating-and-using-a-usb-recovery-drive-for-surface" rel="noopener noreferrer"&gt;Creating and using a USB recovery drive for Surface&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.microsoft.com/en-us/surface-recovery-image" rel="noopener noreferrer"&gt;Official MS Surface Recovery Image Download&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/@derailed.dash/should-you-switch-to-a-windows-arm-laptop-my-experience-of-the-surface-laptop-7-f43725133f24#" rel="noopener noreferrer"&gt;Should You Switch to a Windows ARM Laptop? My Experience of the Surface Laptop 7&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dazbo.co.uk" rel="noopener noreferrer"&gt;My Portfolio Site&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>laptopupgrade</category>
      <category>surfacelaptop</category>
      <category>microsoftsurface</category>
      <category>ssd</category>
    </item>
  </channel>
</rss>
