<?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: Robina Mirbahar</title>
    <description>The latest articles on DEV Community by Robina Mirbahar (@robinamirbahar).</description>
    <link>https://dev.to/robinamirbahar</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%2F698191%2Fe5045ba7-748d-40fc-a918-03ac63516ea9.png</url>
      <title>DEV Community: Robina Mirbahar</title>
      <link>https://dev.to/robinamirbahar</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/robinamirbahar"/>
    <language>en</language>
    <item>
      <title>Building RailPulse AI: Deploying an Open-Source Railway Dispatch Agent with Gemma and Google Cloud Run</title>
      <dc:creator>Robina Mirbahar</dc:creator>
      <pubDate>Sat, 07 Nov 2026 07:35:33 +0000</pubDate>
      <link>https://dev.to/gde/building-railpulse-ai-deploying-an-open-source-railway-dispatch-agent-with-gemma-and-google-cloud-2b9g</link>
      <guid>https://dev.to/gde/building-railpulse-ai-deploying-an-open-source-railway-dispatch-agent-with-gemma-and-google-cloud-2b9g</guid>
      <description>&lt;p&gt;&lt;strong&gt;Author:&lt;/strong&gt; Robina Mirbahar&lt;br&gt;&lt;br&gt;
&lt;em&gt;AI/ML Google Developer Expert (GDE) | Google Cloud Champion Innovator&lt;/em&gt;&lt;br&gt;&lt;br&gt;
&lt;em&gt;GitHub Blueprint:&lt;/em&gt; &lt;a href="https://github.com/RobinaMirbahar/railpulse-gemma-cloudrun" rel="noopener noreferrer"&gt;RobinaMirbahar/railpulse-gemma-cloudrun&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;em&gt;YouTube Walkthrough:&lt;/em&gt; &lt;a href="https://www.youtube.com/@RobinaCodesAI" rel="noopener noreferrer"&gt;@RobinaCodesAI&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%2Fl5rbps3gk1nwcd0jatsp.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fl5rbps3gk1nwcd0jatsp.jpg" alt="RailPulse AI Banner" width="800" height="447"&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%2F6is3gwp3nfu35yw7hxev.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%2F6is3gwp3nfu35yw7hxev.png" alt="Robina Mirbahar presenting RailPulse AI, Gemma 4, and Cloud Run at DevFest Baku 2026, ADA University" width="798" height="191"&gt;&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;em&gt;Robina Mirbahar presenting RailPulse AI, Gemma 4, and Cloud Run at DevFest Baku 2026, ADA University.&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;Most artificial intelligence tutorials show you how to build chatbots that write poems, summarize PDFs, or generate boilerplate code. &lt;/p&gt;

&lt;p&gt;Those demos are fun, but they do not reflect the harsh reality of engineering in mission-critical industries. &lt;/p&gt;

&lt;p&gt;When you deploy AI to manage physical operations, like freight trains moving across thousands of kilometers, a generic chatbot is not just useless; it can be dangerous. A hallucinated speed limit or a delayed signal alert can lead to catastrophic hardware failure or derailment. &lt;/p&gt;

&lt;p&gt;At &lt;strong&gt;DevFest Baku 2026&lt;/strong&gt; at ADA University, I wanted to show developers how to build an enterprise-grade AI system that solves a real operational problem. We built and deployed &lt;strong&gt;RailPulse AI&lt;/strong&gt;, an autonomous, safety-critical railway dispatch and live-tracking agent powered by &lt;strong&gt;Google's open-weights Gemma models&lt;/strong&gt;, the &lt;strong&gt;Google Agent Development Kit (ADK)&lt;/strong&gt;, and &lt;strong&gt;Google Cloud Run&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In this article, I will walk you through the complete architecture, how we used function calling with deterministic safety interlocks, and how you can run open-weights agents serverlessly in production.&lt;/p&gt;


&lt;h2&gt;
  
  
  The Real-World Engineering Problem
&lt;/h2&gt;

&lt;p&gt;Railway corridors run on tight margins. Dispatchers must continuously monitor:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Real-Time Telemetry:&lt;/strong&gt; GPS coordinates, axle bearing temperatures, and locomotive velocity.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Corridor Weather Extremes:&lt;/strong&gt; Sudden crosswinds along coastal or mountain tracks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Schedule Recovery:&lt;/strong&gt; Balancing delays against passenger connection deadlines and single-track passing sidings.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When an emergency happens, dispatchers do not have time to sift through fragmented SCADA dashboards and thousand-line logs. They need an intelligent system that aggregates live telemetry, cross-references signaling rules, and synthesizes clear, actionable dispatch advisories.&lt;/p&gt;

&lt;p&gt;Crucially, &lt;strong&gt;the system cannot hallucinate&lt;/strong&gt;. It must combine the natural reasoning of an LLM with the deterministic predictability of hard-coded safety rules.&lt;/p&gt;


&lt;h2&gt;
  
  
  The RailPulse AI Architecture
&lt;/h2&gt;

&lt;p&gt;Here is the high-level system design we implemented in &lt;a href="https://github.com/RobinaMirbahar/railpulse-gemma-cloudrun" rel="noopener noreferrer"&gt;&lt;code&gt;RobinaMirbahar/railpulse-gemma-cloudrun&lt;/code&gt;&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌─────────────────────────────────────────────────────────────┐
│                 Streamlit Operator Cockpit                  │
│       Interactive SVG Gauges • Multi-Language (EN/AZ/RU)    │
└──────────────────────────────┬──────────────────────────────┘
                               │ HTTPS / JSON
                               ▼
┌─────────────────────────────────────────────────────────────┐
│                 Google Cloud Run Service                    │
│                                                             │
│   ┌─────────────────────────────────────────────────────┐   │
│   │             Google ADK Agent Orchestrator           │   │
│   │                                                     │   │
│   │  ┌─────────────────┐       ┌─────────────────────┐  │   │
│   │  │   Gemma Model   │ ◄───► │  Tool Declarations  │  │   │
│   │  │  (Open-Weights) │       │   Function Calling  │  │   │
│   │  └─────────────────┘       └──────────┬──────────┘  │   │
│   └───────────────────────────────────────┼─────────────┘   │
│                                           ▼                 │
│   ┌─────────────────────────────────────────────────────┐   │
│   │       Deterministic Safety Interlocks (Python)      │   │
│   │   • Hard Wind Speed Limits (Wind &amp;gt; 65 km/h -&amp;gt; 80)   │   │
│   │   • Absolute Signal Overrides (Red Signal = STOP)   │   │
│   │   └───────────────────────────────────┬─────────────┘   │
│                                           ▼                 │
│   ┌─────────────────────────────────────────────────────┐   │
│   │         Pydantic Structured Advisory Schema         │   │
│   │           RailDispatchAdvisory Validation               │   │
│   └─────────────────────────────────────────────────────┘   │
└─────────────────────────────────────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  1. Grounding the Agent: Real-World Tools via Function Calling
&lt;/h2&gt;

&lt;p&gt;Rather than letting Gemma guess railway conditions, we gave the agent access to dedicated telemetry tools using Google ADK function calling:&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_live_train_telemetry&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;train_id&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;-&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="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Fetch live GPS, speed, bearing temperatures, and locomotive health.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;pass&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;check_corridor_signals_and_wind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;corridor_id&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;-&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="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Query wayside signal states (Green/Yellow/Red) and track anemometers.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;pass&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;calculate_schedule_recovery&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;train_id&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;current_delay_min&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&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="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Calculate speed profiles needed to recover schedule without exceeding corridor limits.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;pass&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When an operator asks:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"Train 102 is approaching the Absheron corridor 14 minutes behind schedule. Can we accelerate to recover time?"&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Gemma does not guess. It autonomously calls &lt;code&gt;check_corridor_signals_and_wind(corridor="Absheron")&lt;/code&gt; and &lt;code&gt;get_live_train_telemetry(train_id="102")&lt;/code&gt; to gather factual state before generating a response.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. Deterministic Safety Interlocks: Why the LLM Does Not Make the Final Safety Call
&lt;/h2&gt;

&lt;p&gt;In physical systems, &lt;strong&gt;you never give an LLM sole authority over life-safety decisions.&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;If the model experiences a temporary context confusion, it might suggest maintaining 140 km/h in a 90 km/h windstorm. To prevent this, we built a two-tier architecture:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Tier 1 (Cognitive Reasoning):&lt;/strong&gt; Gemma analyzes the situation, extracts the context, and proposes a schedule recovery plan.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tier 2 (Deterministic Guardrails):&lt;/strong&gt; A hard-coded Python interlock inspects the output against physical invariants before delivering the advisory:
&lt;/li&gt;
&lt;/ol&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;SafetyInterlock&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;MAX_HIGH_WIND_SPEED_KMH&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;80.0&lt;/span&gt;
    &lt;span class="n"&gt;HIGH_WIND_THRESHOLD_KMH&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;65.0&lt;/span&gt;

    &lt;span class="nd"&gt;@classmethod&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;enforce_guardrails&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;advisory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;RailDispatchAdvisory&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;wind_speed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;signal_state&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;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;RailDispatchAdvisory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# Rule 1: High Wind Speed Clamp
&lt;/span&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;wind_speed&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HIGH_WIND_THRESHOLD_KMH&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;advisory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;recommended_speed_kmh&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MAX_HIGH_WIND_SPEED_KMH&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;advisory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;recommended_speed_kmh&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MAX_HIGH_WIND_SPEED_KMH&lt;/span&gt;
                &lt;span class="n"&gt;advisory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;safety_flags&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&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;GUARDRAIL ENFORCED: Wind speed &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;wind_speed&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; km/h exceeds threshold. Speed clamped to 80 km/h.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
                &lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# Rule 2: Absolute Red Signal Override
&lt;/span&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;signal_state&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;RED&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;advisory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;recommended_speed_kmh&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.0&lt;/span&gt;
            &lt;span class="n"&gt;advisory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;action_required&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;EMERGENCY_STOP&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
            &lt;span class="n"&gt;advisory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;safety_flags&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;CRITICAL: Red signal detected. Immediate stop enforced.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;advisory&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This guarantees that even if an operator or a prompt edge case attempts to push the model beyond safe boundaries, the mathematical and physical guardrails cannot be bypassed.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. Strict Output Contracts with Pydantic
&lt;/h2&gt;

&lt;p&gt;To ensure the downstream operator dashboard never crashes due to unstructured freeform text, all agent advisories are validated against a strict schema:&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;pydantic&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;BaseModel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Field&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;typing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Optional&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;RailDispatchAdvisory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BaseModel&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;train_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;recommended_speed_kmh&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(...,&lt;/span&gt; &lt;span class="n"&gt;ge&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;le&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;160.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;delay_delta_minutes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;
    &lt;span class="n"&gt;signal_status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;action_required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;advisory_summary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;safety_flags&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&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="p"&gt;[]&lt;/span&gt;
    &lt;span class="n"&gt;confidence_score&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(...,&lt;/span&gt; &lt;span class="n"&gt;ge&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;le&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the agent’s response does not conform to this structure, the ADK pipeline rejects it before it ever reaches the dispatcher cockpit.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. Packaging and Deploying on Google Cloud Run
&lt;/h2&gt;

&lt;p&gt;To make RailPulse AI truly production-ready, we containerized the application with Docker and deployed it to Google Cloud Run.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Cloud Run for AI Agents?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Serverless Economics:&lt;/strong&gt; Rail telematics spikes during train arrivals and yard movements, with quiet periods in between. Cloud Run scales dynamically from zero to handle spikes and scales back down when traffic subsides.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Air-Gapped and Sovereign Edge Ready:&lt;/strong&gt; Because Gemma is an open-weights model, you can run inference entirely inside your own private VPC without sending sensitive operational telemetry to third-party proprietary APIs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;One-Command Deployment:&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gcloud run deploy railpulse-agent &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--source&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--platform&lt;/span&gt; managed &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--region&lt;/span&gt; europe-west1 &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--allow-unauthenticated&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--memory&lt;/span&gt; 4Gi &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--cpu&lt;/span&gt; 2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  5. Localized Operator Experience: Multi-Language Dispatch (EN / AZ / RU)
&lt;/h2&gt;

&lt;p&gt;In international logistics corridors like the Trans-Caspian International Transport Route, operators speak multiple languages. &lt;/p&gt;

&lt;p&gt;Because Gemma possesses strong multilingual representations, RailPulse AI seamlessly provides telemetry readouts, safety flags, and advisory summaries in English, Azerbaijani (Azərbaycan dili), and Russian (Русский), allowing local dispatchers to interact with the system in their native language while maintaining uniform safety semantics under the hood.&lt;/p&gt;




&lt;h2&gt;
  
  
  Key Lessons from Building RailPulse AI
&lt;/h2&gt;

&lt;p&gt;Building this project and presenting it at DevFest Baku reinforced three fundamental principles for building agentic AI:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Agents are More Than Prompts:&lt;/strong&gt; A production agent is 20% prompt engineering and 80% systems engineering: tool definitions, schema validation, network resilience, and error handling.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deterministic Guardrails are Mandatory:&lt;/strong&gt; In physical, industrial, or medical applications, never let an LLM have unchecked authority. Pair cognitive reasoning with deterministic code interlocks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Open-Weights Models are Production Ready:&lt;/strong&gt; With models like Gemma and serverless platforms like Google Cloud Run, individual developers and enterprise teams can build custom, private, and fully auditable AI systems without paying thousands of dollars in proprietary API costs.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Explore the Code and Video Walkthrough
&lt;/h2&gt;

&lt;p&gt;The complete codebase, Streamlit operator dashboard, Dockerfile, and Google ADK implementation are open-source and ready to clone:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;GitHub Repository:&lt;/strong&gt; &lt;a href="https://github.com/RobinaMirbahar/railpulse-gemma-cloudrun" rel="noopener noreferrer"&gt;https://github.com/RobinaMirbahar/railpulse-gemma-cloudrun&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;YouTube Channel:&lt;/strong&gt; &lt;a href="https://www.youtube.com/@RobinaCodesAI" rel="noopener noreferrer"&gt;https://www.youtube.com/@RobinaCodesAI&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Special thanks to the GDG Baku team, ADA University, and all the incredible participants at DevFest Baku 2026 for making this hands-on workshop such a rewarding experience!&lt;/p&gt;

</description>
      <category>ai</category>
      <category>googlecloud</category>
      <category>opensource</category>
      <category>python</category>
    </item>
    <item>
      <title>MemoriaViva: A Cute Ghost in the Machine That Preserves Family Oral Histories &amp; Heirloom Recipes with Gemma 4 &amp; Google ADK</title>
      <dc:creator>Robina Mirbahar</dc:creator>
      <pubDate>Tue, 27 Oct 2026 20:05:29 +0000</pubDate>
      <link>https://dev.to/gde/memoriaviva-a-cute-ghost-in-the-machine-that-preserves-family-oral-histories-heirloom-recipes-5g4g</link>
      <guid>https://dev.to/gde/memoriaviva-a-cute-ghost-in-the-machine-that-preserves-family-oral-histories-heirloom-recipes-5g4g</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/hacktoberfest-week4-2026-10-26"&gt;Hacktoberfest Open-Source AI Challenge Week 4: Ghost in the Machine&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;Every family has a &lt;strong&gt;"Ghost in the Machine"&lt;/strong&gt; waiting to be remembered: a crackly 48-second WhatsApp voice note from a grandfather explaining how to brew monsoon ginger &lt;em&gt;kahwa&lt;/em&gt;, a flour-stained index card in a grandmother's handwriting where measurements are written as &lt;em&gt;"two cupped handfuls of wheat flour and warm milk until the dough sighs softly,"&lt;/em&gt; or a shoebox of fading photographs from decades ago.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;MemoriaViva&lt;/strong&gt; (&lt;em&gt;Living Memory&lt;/em&gt;) is a warm, local-first &lt;strong&gt;Family Oral-History Weaver, Heirloom Recipe Standardizer &amp;amp; Digital Family Storybook&lt;/strong&gt; powered by open-weights &lt;strong&gt;Google Gemma 4&lt;/strong&gt; (&lt;code&gt;google/gemma-4-27b-it&lt;/code&gt;), &lt;strong&gt;Google Agent Development Kit (ADK)&lt;/strong&gt;, &lt;strong&gt;Google BigQuery&lt;/strong&gt; (Family Vault table schema), and &lt;strong&gt;Sentry Agent Tracing&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%2F4gug4vkxe5hglmtxl0zh.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4gug4vkxe5hglmtxl0zh.jpg" alt="MemoriaViva Scrapbook Architecture Diagram" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I interpreted this week's theme in the warm spirit of &lt;strong&gt;Dia de los Muertos&lt;/strong&gt; and South Asian ancestral remembrance: &lt;strong&gt;Lumi&lt;/strong&gt;, a friendly, spectacle-wearing memory ghost living on the same machine that reads fragmented family voice transcripts and handwritten recipe notes, preserves the elder's exact cultural idioms verbatim, converts poetic ancestral measurements (&lt;em&gt;"a three-finger pinch of saffron,"&lt;/em&gt; &lt;em&gt;"four brimming clay bowls of flour"&lt;/em&gt;) into reproducible metric grams and milliliters, and exports a &lt;strong&gt;Dual-Mode Family Vault&lt;/strong&gt; consisting of a self-contained &lt;strong&gt;W3C HTML5 Family Storybook (&lt;code&gt;4,909 bytes&lt;/code&gt;)&lt;/strong&gt; plus a &lt;strong&gt;Google BigQuery Newline-Delimited JSON (&lt;code&gt;exported_memories.jsonl&lt;/code&gt;, &lt;code&gt;4,344 bytes&lt;/code&gt;)&lt;/strong&gt; table export.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Heritage Archival Metric&lt;/th&gt;
&lt;th&gt;Raw Family Voice Notes &amp;amp; Index Cards&lt;/th&gt;
&lt;th&gt;MemoriaViva (Gemma 4 + Google ADK + BigQuery Vault)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Ancestral Measurement Format&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Ambiguous (&lt;em&gt;"a handful," "a teacup," "until soft"&lt;/em&gt;)&lt;/td&gt;
&lt;td&gt;Dual-Format: Verbatim Poetic Phrase + Exact Metric (&lt;code&gt;g&lt;/code&gt; / &lt;code&gt;ml&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Poetic Units Converted in Benchmark&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;9 unstructured phrases across 3 family recipes&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;9 of 9 (100.0% deterministic metric conversion)&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Dough &amp;amp; Liquid Hydration Validation&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Guesswork (often fails for younger generations)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Deterministic Culinary Ratio Guardrail (45.0% to 95.0% bounds)&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Local Inference Privacy&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Uploaded to third-party commercial LLM APIs&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0 bytes Transmitted (127.0.0.1 Air-Gap Socket Lock)&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Family Vault Storage&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Locked in proprietary SaaS apps&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Local W3C HTML5 (4,909 B) + BigQuery JSONL Vault Table (4,344 B)&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;You can run the complete &lt;strong&gt;MemoriaViva&lt;/strong&gt; three-stage &lt;strong&gt;Gemma 4 + Google ADK + Sentry Agent Tracing&lt;/strong&gt; benchmark, verify the interactive &lt;strong&gt;FastAPI Family Storybook Dashboard&lt;/strong&gt;, and export both the offline HTML5 book and the &lt;strong&gt;Google BigQuery JSONL Family Vault&lt;/strong&gt; with a single command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python scripts/run_memoriaviva_demo.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;========================================================================================
👻🕯️ MEMORIAVIVA: CUTE GHOST IN THE MACHINE (GEMMA 4 + ADK + BIGQUERY VAULT)
========================================================================================
  Model                  : google/gemma-4-27b-it (100% Local Ollama / vLLM)
  Air-Gapped Endpoint    : http://127.0.0.1:11434 (0 Cloud Egress Verified)
  Family Memories Loaded : 3 ancestral voice &amp;amp; recipe records
----------------------------------------------------------------------------------------
  [MEM-01] Dadi Jan's Partition-Era Cardamom &amp;amp; Saffron Sweet Bread (1947)
    Elder Quote Preserved : 'Measure the warm milk with your fingertips; when the dough sighs softly, the cardamom is awake.'
    • 'two generous cupped handfuls of stone-ground wheat flour'  ➔  240.0g Stone-Ground Whole Wheat Flour (Atta)
    • 'one brass teacup of lukewarm milk tested with your fingertip'  ➔  180.0ml Whole Warm Milk (38C)
    • 'seven bruised green cardamom pods &amp;amp; a three-finger pinch of saffron'  ➔  4.4g Crushed Green Cardamom &amp;amp; Kashmiri Saffron
    Hydration Audit       : 75.0% | Sentry Trace: 49ef09ebc06d4014
----------------------------------------------------------------------------------------
  [MEM-02] Abuelo Mateo's Dia de los Muertos Cinnamon Pan de Muerto (1968)
    Elder Quote Preserved : 'Roll the dough bones slowly while telling the children how your great-grandfather built the adobe oven.'
    • 'four brimming clay bowls of bread flour'  ➔  500.0g Unbleached Artisan Bread Flour
    • 'a warm splash of orange blossom water &amp;amp; melted butter'  ➔  325.0ml Orange Blossom Infusion &amp;amp; Warm Milk
    • 'two thumbs of freshly grated orange zest and Ceylon cinnamon'  ➔  12.0g Organic Orange Zest &amp;amp; Ground Cinnamon
    Hydration Audit       : 65.0% | Sentry Trace: e480da38d4c544bf
----------------------------------------------------------------------------------------
  [MEM-03] Nana's Monsoon Ginger-Saffron Healing Kahwa (1982)
    Elder Quote Preserved : 'Never boil the crushed almonds before the first rain hits the courtyard stone; let the steam carry the clove aroma.'
    • 'three copper cups of spring water'  ➔  600.0ml Filtered Spring Water
    • 'a thumb-sized root of crushed fresh ginger &amp;amp; four cloves'  ➔  18.0g Fresh Crushed Ginger &amp;amp; Whole Cloves
    • 'a palmful of slivered almonds and wildflower honey'  ➔  37.0g Blanched Slivered Almonds &amp;amp; Raw Honey
    Hydration Audit       : 100.0% | Sentry Trace: fbfe81215ad54101
----------------------------------------------------------------------------------------
  Poetic Units Converted : 9 of 9 (100.0% deterministic metric accuracy)
  Sentry Spans Recorded  : 18 gen_ai.agent / gen_ai.tool spans
  FastAPI Ofrenda Check  : GET / (200 OK) | GET /api/memories (200 OK)
  Family Vault Export    : 4909 bytes HTML5 + 4344 bytes BigQuery JSONL (3 rows)
  Cloud Bytes Transmitted: 0 bytes during local Gemma 4 inference
========================================================================================
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Interactive Family Storybook &amp;amp; Recipe Weaver UI Preview
&lt;/h3&gt;

&lt;p&gt;&lt;a 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%2Furvbab74mlufhaj6n19z.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Furvbab74mlufhaj6n19z.jpg" alt="MemoriaViva White-Background Storybook UI" width="799" height="436"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  Code
&lt;/h2&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/RobinaMirbahar" rel="noopener noreferrer"&gt;
        RobinaMirbahar
      &lt;/a&gt; / &lt;a href="https://github.com/RobinaMirbahar/memoriaviva-gemma-ofrenda" rel="noopener noreferrer"&gt;
        memoriaviva-gemma-ofrenda
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      MemoriaViva: Cute Ghost in the Machine — 100% Local Open-Weights Gemma 4, Google ADK &amp;amp; Sentry Agent Tracing Family Oral-History &amp;amp; Heirloom Recipe Weaver (Hacktoberfest 2026)
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;👻🕯️ MemoriaViva: Cute Ghost in the Machine for Family Oral Histories &amp;amp; Heirloom Recipes (Gemma 4 + Google ADK + BigQuery Family Vault)&lt;/h1&gt;
&lt;/div&gt;

&lt;p&gt;&lt;a href="https://github.com/RobinaMirbahar/memoriaviva-gemma-ofrenda/actions/workflows/ci.yml" rel="noopener noreferrer"&gt;&lt;img src="https://github.com/RobinaMirbahar/memoriaviva-gemma-ofrenda/actions/workflows/ci.yml/badge.svg" alt="CI Verification"&gt;&lt;/a&gt;
&lt;a href="https://dev.to/challenges/hacktoberfest-week4-2026-10-26" rel="nofollow"&gt;&lt;img src="https://camo.githubusercontent.com/07b88c6037059c547db9f6c7c0d73374c6ab1ba82f0745157e0f30da2db608a1/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4861636b746f62657266657374253230323032362d47686f7374253230696e2532307468652532304d616368696e652d6635396530623f7374796c653d666f722d7468652d6261646765266c6f676f3d676974687562" alt="Hacktoberfest 2026"&gt;&lt;/a&gt;
&lt;a href="https://ai.google.dev/gemma/docs" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/1fa845c04ecfeac031811adbb84c57bf891b4ad604563984d9d595ac9c38acfb/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4f70656e2d2d576569676874732d47656d6d612532303425323028323742292d3432383546343f7374796c653d666f722d7468652d6261646765266c6f676f3d676f6f676c65266c6f676f436f6c6f723d7768697465" alt="Google Gemma 4"&gt;&lt;/a&gt;
&lt;a href="https://google.github.io/adk-docs/" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/222228051577e3cc74caed3c2025de23082b72eefdab896cea50677934dad400/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4f726368657374726174696f6e2d476f6f676c6525323041444b2d3334413835333f7374796c653d666f722d7468652d6261646765266c6f676f3d676f6f676c65636c6f7564266c6f676f436f6c6f723d7768697465" alt="Google ADK"&gt;&lt;/a&gt;
&lt;a href="https://cloud.google.com/bigquery/docs/loading-data-cloud-storage-json" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/8ee6e1c86b721de16abc3dee37b3116c3ad2017959b6bdb7f53b7a239c2124fd/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f46616d696c792532305661756c742d476f6f676c6525323042696751756572792d3432383546343f7374796c653d666f722d7468652d6261646765266c6f676f3d676f6f676c656269677175657279266c6f676f436f6c6f723d7768697465" alt="Google BigQuery"&gt;&lt;/a&gt;
&lt;a href="https://docs.sentry.io/platforms/python/tracing/ai-agents/" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/fb5b96ac95aafbcbf3e35f79dc1b6568c1ab6bf8e40d56b5107a9431cc97f8f1/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4f62736572766162696c6974792d53656e7472792532304167656e7425323054726163696e672d3336324435393f7374796c653d666f722d7468652d6261646765266c6f676f3d73656e747279266c6f676f436f6c6f723d7768697465" alt="Sentry Agent Tracing"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer nofollow" href="https://raw.githubusercontent.com/RobinaMirbahar/memoriaviva-gemma-ofrenda/main/articles/memoriaviva/cover_google_ghost_style.6e9508ea.jpg"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2FRobinaMirbahar%2Fmemoriaviva-gemma-ofrenda%2Fmain%2Farticles%2Fmemoriaviva%2Fcover_google_ghost_style.6e9508ea.jpg" alt="MemoriaViva Cover"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Author &amp;amp; Architect:&lt;/strong&gt; &lt;a href="https://github.com/RobinaMirbahar" rel="noopener noreferrer"&gt;Robina Mirbahar&lt;/a&gt; (Google Developer Expert in Cloud &amp;amp; AI · Google Cloud Champion Innovator · Author of &lt;a href="https://amazon.com/dp/B0GWCZWCF4" rel="nofollow noopener noreferrer"&gt;&lt;em&gt;AI Engineering&lt;/em&gt;&lt;/a&gt;)&lt;br&gt;
&lt;strong&gt;Challenge Track:&lt;/strong&gt; Hacktoberfest Open-Source AI Challenge Week 4: &lt;em&gt;Ghost in the Machine&lt;/em&gt; (&lt;code&gt;#hf26challenge&lt;/code&gt;, &lt;code&gt;#gemma&lt;/code&gt;, &lt;code&gt;#googleai&lt;/code&gt;)&lt;br&gt;
&lt;strong&gt;Core Stack:&lt;/strong&gt; Open-Weights &lt;strong&gt;Google Gemma 4&lt;/strong&gt; (&lt;code&gt;google/gemma-4-27b-it&lt;/code&gt;), &lt;strong&gt;Google Agent Development Kit (ADK)&lt;/strong&gt;, &lt;strong&gt;Google BigQuery&lt;/strong&gt; (JSONL Family Vault Table), &lt;strong&gt;Google AI Studio&lt;/strong&gt;, &lt;strong&gt;FastAPI&lt;/strong&gt;, &lt;strong&gt;Pydantic v2&lt;/strong&gt;, and &lt;strong&gt;Sentry Agent Tracing&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;📊 Live Architecture Telemetry &amp;amp; Benchmark Highlights&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;
  &lt;a rel="noopener noreferrer nofollow" href="https://raw.githubusercontent.com/RobinaMirbahar/memoriaviva-gemma-ofrenda/main/assets/card_gemma.svg"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2FRobinaMirbahar%2Fmemoriaviva-gemma-ofrenda%2Fmain%2Fassets%2Fcard_gemma.svg" alt="Gemma 4 Engine" width="23%"&gt;&lt;/a&gt;
  &lt;a rel="noopener noreferrer nofollow" href="https://raw.githubusercontent.com/RobinaMirbahar/memoriaviva-gemma-ofrenda/main/assets/card_adk.svg"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2FRobinaMirbahar%2Fmemoriaviva-gemma-ofrenda%2Fmain%2Fassets%2Fcard_adk.svg" alt="Google ADK Pipeline" width="23%"&gt;&lt;/a&gt;
  &lt;a rel="noopener noreferrer nofollow" href="https://raw.githubusercontent.com/RobinaMirbahar/memoriaviva-gemma-ofrenda/main/assets/card_privacy.svg"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2FRobinaMirbahar%2Fmemoriaviva-gemma-ofrenda%2Fmain%2Fassets%2Fcard_privacy.svg" alt="Air-Gapped Privacy" width="23%"&gt;&lt;/a&gt;
  &lt;a rel="noopener noreferrer nofollow" href="https://raw.githubusercontent.com/RobinaMirbahar/memoriaviva-gemma-ofrenda/main/assets/card_sentry.svg"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2FRobinaMirbahar%2Fmemoriaviva-gemma-ofrenda%2Fmain%2Fassets%2Fcard_sentry.svg" alt="Sentry Agent Tracing" width="23%"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;&lt;div class="table-wrapper-paragraph"&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;table&gt;

&lt;thead&gt;

&lt;tr&gt;

&lt;th&gt;Heritage Archival Metric&lt;/th&gt;

&lt;th&gt;Raw Family Voice Notes &amp;amp; Index Cards&lt;/th&gt;

&lt;th&gt;MemoriaViva (Gemma 4 + Google ADK + BigQuery Vault)&lt;/th&gt;

&lt;/tr&gt;

&lt;/thead&gt;

&lt;tbody&gt;

&lt;tr&gt;

&lt;td&gt;&lt;strong&gt;Ancestral Measurement Format&lt;/strong&gt;&lt;/td&gt;

&lt;td&gt;Ambiguous (&lt;em&gt;"a handful," "a teacup," "until soft"&lt;/em&gt;)&lt;/td&gt;

&lt;td&gt;Dual-Format: Verbatim Poetic Phrase + Exact Metric (&lt;code&gt;g&lt;/code&gt; / &lt;code&gt;ml&lt;/code&gt;)&lt;/td&gt;

&lt;/tr&gt;

&lt;/tbody&gt;

&lt;/table&gt;&lt;/div&gt;…&lt;p&gt;&lt;/p&gt;&lt;/div&gt;
&lt;br&gt;
  &lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/RobinaMirbahar/memoriaviva-gemma-ofrenda" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;


&lt;h3&gt;
  
  
  Repository Structure
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;memoriaviva-gemma-ofrenda/
├── memoriaviva/
│   ├── __init__.py
│   ├── schemas.py        # Pydantic v2 schemas for RawFamilyMemory &amp;amp; WovenHeirloomStoryCard
│   ├── guardrails.py     # Air-gapped 127.0.0.1 socket lock &amp;amp; culinary hydration validator
│   ├── agents.py         # 3-stage Google ADK SequentialAgent + Gemma 4 + Sentry Tracer
│   └── dashboard.py      # FastAPI Family Storybook &amp;amp; static HTML5 exporter
├── scripts/
│   └── run_memoriaviva_demo.py  # Benchmark + HTML5 &amp;amp; BigQuery JSONL Family Vault exporter
├── articles/memoriaviva/        # Illustrations, BigQuery schema &amp;amp; benchmark evidence
└── requirements.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  How I Built It
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fflkyssest6skx7c550tf.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fflkyssest6skx7c550tf.jpg" alt="MemoriaViva Technical Architecture on White Background" width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I built &lt;strong&gt;MemoriaViva&lt;/strong&gt; by combining &lt;strong&gt;Google's open-weights AI ecosystem&lt;/strong&gt; and &lt;strong&gt;Google Cloud data architecture&lt;/strong&gt; with deterministic Python safety guardrails:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Open-Weights Google Gemma 4 (&lt;code&gt;google/gemma-4-27b-it&lt;/code&gt;):&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Configured for local serving via &lt;strong&gt;Ollama / vLLM&lt;/strong&gt; on &lt;code&gt;http://127.0.0.1:11434&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Gemma 4 preserves South Asian (&lt;em&gt;Urdu/Sindhi&lt;/em&gt;) and Latin American (&lt;em&gt;Spanish&lt;/em&gt;) culinary idioms alongside structured JSON output.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Google Agent Development Kit (ADK) 3-Stage &lt;code&gt;SequentialAgent&lt;/code&gt; Pipeline (&lt;code&gt;memoriaviva/agents.py&lt;/code&gt;):&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Stage 1 (&lt;code&gt;OralHistoryWhisperAgent&lt;/code&gt;):&lt;/strong&gt; Extracts the elder's verbatim quote and weaves the historical context (&lt;em&gt;1947 Partition-era Hyderabad&lt;/em&gt;, &lt;em&gt;1968 Oaxaca Dia de los Muertos&lt;/em&gt;, &lt;em&gt;1982 Monsoon Courtyard&lt;/em&gt;) into a structured narrative.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stage 2 (&lt;code&gt;HeirloomRecipeAlchemistAgent&lt;/code&gt;):&lt;/strong&gt; Translates tactile, non-standard measurements (&lt;em&gt;"two generous cupped handfuls of stone-ground wheat flour"&lt;/em&gt;) into structured &lt;code&gt;StandardizedIngredient&lt;/code&gt; objects (&lt;code&gt;240.0g&lt;/code&gt;) while keeping the original phrase beside it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stage 3 (&lt;code&gt;CandlelitOfrendaCuratorAgent&lt;/code&gt;):&lt;/strong&gt; Validates the memory against &lt;code&gt;WovenHeirloomStoryCard&lt;/code&gt; and prepares the record for the &lt;strong&gt;Family Vault&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deterministic Privacy &amp;amp; Culinary Guardrails (&lt;code&gt;memoriaviva/guardrails.py&lt;/code&gt;):&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;verify_air_gapped_endpoint()&lt;/code&gt;:&lt;/strong&gt; Rejects any non-local hostname (&lt;code&gt;127.0.0.1&lt;/code&gt; / &lt;code&gt;localhost&lt;/code&gt; / &lt;code&gt;::1&lt;/code&gt;) during inference, guaranteeing that &lt;code&gt;0 bytes&lt;/code&gt; of raw family recordings are sent to external LLM APIs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;compute_and_validate_hydration()&lt;/code&gt;:&lt;/strong&gt; Audits the ratio of liquid milliliters to dry flour grams (&lt;code&gt;75.0%&lt;/code&gt; for &lt;code&gt;MEM-01&lt;/code&gt;, &lt;code&gt;65.0%&lt;/code&gt; for &lt;code&gt;MEM-02&lt;/code&gt;, and &lt;code&gt;100.0%&lt;/code&gt; for liquid infusion &lt;code&gt;MEM-03&lt;/code&gt;) within deterministic bounds (&lt;code&gt;45.0%&lt;/code&gt; to &lt;code&gt;95.0%&lt;/code&gt; for doughs).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dual-Mode Family Vault (Local W3C HTML5 + Google BigQuery Table Schema):&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;By default, &lt;code&gt;scripts/run_memoriaviva_demo.py&lt;/code&gt; writes the woven memories to a self-contained &lt;strong&gt;W3C HTML5 Family Storybook&lt;/strong&gt; (&lt;code&gt;4,909 bytes&lt;/code&gt;) and a &lt;strong&gt;Newline-Delimited JSON (&lt;code&gt;exported_memories.jsonl&lt;/code&gt;, &lt;code&gt;4,344 bytes&lt;/code&gt;)&lt;/strong&gt; file alongside &lt;a href="https://github.com/RobinaMirbahar/memoriaviva-gemma-ofrenda/blob/main/articles/memoriaviva/evidence/bigquery_vault_schema.json" rel="noopener noreferrer"&gt;&lt;code&gt;bigquery_vault_schema.json&lt;/code&gt;&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Because &lt;code&gt;standardized_recipe&lt;/code&gt; is structured as a &lt;code&gt;RECORD REPEATED&lt;/code&gt; nested array, families who want to back up their structured cookbook across continents in their own private Google Cloud project can load the JSONL archive directly into a &lt;strong&gt;Google BigQuery&lt;/strong&gt; table (&lt;code&gt;memoriaviva_vault.heirloom_memories&lt;/code&gt;):
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bq load &lt;span class="nt"&gt;--source_format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;NEWLINE_DELIMITED_JSON &lt;span class="se"&gt;\&lt;/span&gt;
  memoriaviva_vault.heirloom_memories &lt;span class="se"&gt;\&lt;/span&gt;
  articles/memoriaviva/evidence/exported_memories.jsonl &lt;span class="se"&gt;\&lt;/span&gt;
  articles/memoriaviva/evidence/bigquery_vault_schema.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Sentry Agent Tracing (&lt;code&gt;LocalSentryTracer&lt;/code&gt;):&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Every stage emits OpenTelemetry-compatible &lt;code&gt;gen_ai.agent&lt;/code&gt; and &lt;code&gt;gen_ai.tool&lt;/code&gt; spans capturing model name, ingredient conversion counts, and hydration audit results across all &lt;code&gt;18&lt;/code&gt; recorded spans.
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&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;verify_air_gapped_endpoint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;endpoint_url&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;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Tuple&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;bool&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="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Ensure inference requests only target local open-weights endpoints.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;parsed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;urlparse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;endpoint_url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;allowed_hosts&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;127.0.0.1&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;localhost&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;::1&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="n"&gt;parsed&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hostname&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;allowed_hosts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;True&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;AIR_GAP_OK: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;parsed&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hostname&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; is strictly local (0 cloud bytes).&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;PermissionError&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;PRIVACY_GUARDRAIL_BLOCKED: External host &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;parsed&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hostname&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt; rejected to protect family archive.&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;h2&gt;
  
  
  Why Does Open Innovation Matter?
&lt;/h2&gt;

&lt;p&gt;For a project that handles &lt;strong&gt;intimate family memories, elders' voices, and ancestral heritage&lt;/strong&gt;, open-weights AI provides three concrete engineering guarantees:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Intimate Family Voices Stay on &lt;code&gt;127.0.0.1&lt;/code&gt; (&lt;code&gt;0 bytes&lt;/code&gt; LLM Cloud Egress):&lt;/strong&gt; Families can transcribe and structure voice notes locally with &lt;strong&gt;Gemma 4&lt;/strong&gt; without uploading private recordings to a third-party commercial LLM API.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Works Offline in Courtyards, Villages &amp;amp; Field Recordings:&lt;/strong&gt; When visiting elders in rural towns or recording oral histories without internet connectivity, the local &lt;strong&gt;Gemma 4 + Google ADK&lt;/strong&gt; pipeline runs offline on the same machine.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Open Standards + Private Google BigQuery Family Vault Ownership:&lt;/strong&gt; By exporting a self-contained &lt;strong&gt;W3C HTML5&lt;/strong&gt; file (&lt;code&gt;4,909 bytes&lt;/code&gt;) alongside a &lt;strong&gt;Google BigQuery JSONL&lt;/strong&gt; archive (&lt;code&gt;4,344 bytes&lt;/code&gt;), your family owns both an offline browser-ready book and a structured analytical table under your own IAM control.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  My Agent Session
&lt;/h2&gt;

&lt;p&gt;During the benchmark run, &lt;strong&gt;MemoriaViva&lt;/strong&gt; recorded &lt;strong&gt;18 structured &lt;code&gt;gen_ai.agent&lt;/code&gt; and &lt;code&gt;gen_ai.tool&lt;/code&gt; spans&lt;/strong&gt; across the 3-stage &lt;strong&gt;Google ADK + Gemma 4&lt;/strong&gt; pipeline:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;gen_ai.agent&lt;/code&gt; ➔ &lt;code&gt;OralHistoryWhisperAgent&lt;/code&gt; (&lt;code&gt;model="google/gemma-4-27b-it"&lt;/code&gt;, &lt;code&gt;memory_id="MEM-01"&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;gen_ai.tool&lt;/code&gt; ➔ &lt;code&gt;HeirloomRecipeAlchemistAgent.standardize_units&lt;/code&gt; (&lt;code&gt;ingredients_converted=3&lt;/code&gt;, &lt;code&gt;hydration_pct=75.0&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;gen_ai.agent&lt;/code&gt; ➔ &lt;code&gt;CandlelitOfrendaCuratorAgent&lt;/code&gt; (&lt;code&gt;air_gapped=True&lt;/code&gt;, &lt;code&gt;trace_id="49ef09ebc06d4014"&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The Spirit of It
&lt;/h2&gt;

&lt;p&gt;In almost every culture, from &lt;strong&gt;Dia de los Muertos&lt;/strong&gt; &lt;em&gt;ofrendas&lt;/em&gt; glowing with marigolds in Mexico to family hearths across South Asia, food and storytelling are how we keep the people we love close to us.&lt;/p&gt;

&lt;p&gt;When an elder writes &lt;em&gt;"measure the warm milk with your fingertips; when the dough sighs softly, the cardamom is awake,"&lt;/em&gt; standard recipe apps strip away the voice and leave cold numbers. Conversely, keeping only the poetic phrase leaves younger generations unsure how much &lt;em&gt;"two cupped handfuls"&lt;/em&gt; weighs. Seeing &lt;strong&gt;Gemma 4&lt;/strong&gt; preserve &lt;strong&gt;both&lt;/strong&gt; side-by-side (&lt;code&gt;240.0g Stone-Ground Whole Wheat Flour&lt;/code&gt; and &lt;code&gt;180.0ml Whole Warm Milk&lt;/code&gt; at &lt;code&gt;75.0%&lt;/code&gt; hydration alongside Dadi Jan's exact words) inside a self-contained digital family book and BigQuery Family Vault brought this project to life.&lt;/p&gt;




&lt;h2&gt;
  
  
  Prize Categories
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Best Use of Gemma:&lt;/strong&gt; Uses open-weights &lt;strong&gt;&lt;code&gt;google/gemma-4-27b-it&lt;/code&gt;&lt;/strong&gt; as the core reasoning design inside a 3-stage &lt;strong&gt;Google ADK&lt;/strong&gt; pipeline to preserve multilingual oral histories and deterministically standardize &lt;code&gt;9 of 9&lt;/code&gt; (&lt;code&gt;100.0%&lt;/code&gt;) ancestral culinary measurements locally.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Best Use of Sentry Agent Tracing:&lt;/strong&gt; Instruments every &lt;strong&gt;Google ADK&lt;/strong&gt; agent and tool stage with &lt;code&gt;18&lt;/code&gt; &lt;code&gt;gen_ai.agent&lt;/code&gt; and &lt;code&gt;gen_ai.tool&lt;/code&gt; telemetry spans to audit conversion accuracy and hydration guardrails locally.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>devchallenge</category>
      <category>hf26challenge</category>
      <category>gemma</category>
      <category>googleai</category>
    </item>
    <item>
      <title>From Ancient Epigraphy to 3D Proteins: Exploring google-deepmind/science-skills &amp; Building Custom Plugins in Google Antigravity</title>
      <dc:creator>Robina Mirbahar</dc:creator>
      <pubDate>Sat, 24 Oct 2026 18:56:58 +0000</pubDate>
      <link>https://dev.to/gde/from-ancient-epigraphy-to-3d-proteins-building-plugins-skills-mcp-sidecars-in-google-antigravity-4l1m</link>
      <guid>https://dev.to/gde/from-ancient-epigraphy-to-3d-proteins-building-plugins-skills-mcp-sidecars-in-google-antigravity-4l1m</guid>
      <description>&lt;p&gt;What happens when you ask an AI coding agent to &lt;strong&gt;score a non-coding human genomic variant with AlphaGenome&lt;/strong&gt;, &lt;strong&gt;map a missense mutation onto an AlphaFold 3D protein structure&lt;/strong&gt;, &lt;strong&gt;screen ChEMBL for nanomolar small-molecule inhibitors&lt;/strong&gt;, or &lt;strong&gt;restore a damaged 2,000-year-old Roman inscription using Google DeepMind's Aeneas model&lt;/strong&gt;?&lt;/p&gt;

&lt;p&gt;If you try to stuff 40 scientific APIs, rate limiters, clinical safety guardrails, and 3D WebGL visualizers into a single mega-prompt, the agent collapses under context bloat and hallucinated parameters.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Google Antigravity&lt;/strong&gt; solves this at the runtime level with its &lt;strong&gt;Plugin &amp;amp; Customization Architecture&lt;/strong&gt; - combining &lt;strong&gt;Progressive-Disclosure Skills (&lt;code&gt;SKILL.md&lt;/code&gt;)&lt;/strong&gt;, &lt;strong&gt;Always-On Rules (&lt;code&gt;AGENTS.md&lt;/code&gt;)&lt;/strong&gt;, &lt;strong&gt;Lifecycle Hooks (&lt;code&gt;hooks.json&lt;/code&gt;)&lt;/strong&gt;, &lt;strong&gt;Zero-Leak Credential Protocols&lt;/strong&gt;, and &lt;strong&gt;Model Context Protocol (&lt;code&gt;mcp_config.json&lt;/code&gt;) + Background Sidecars (&lt;code&gt;sidecar.json&lt;/code&gt;)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Instead of just reading the docs, I explored the newly open-sourced &lt;strong&gt;&lt;a href="https://github.com/google-deepmind/science-skills" rel="noopener noreferrer"&gt;Google DeepMind Science Skills (&lt;code&gt;google-deepmind/science-skills&lt;/code&gt;, &lt;code&gt;v1.3.1&lt;/code&gt;)&lt;/a&gt;&lt;/strong&gt; repository (Apache 2.0 / CC-BY 4.0) and built the open-source &lt;strong&gt;&lt;a href="https://github.com/RobinaMirbahar/antigravity-science-plugin-cookbook" rel="noopener noreferrer"&gt;Antigravity Science Plugin Cookbook &amp;amp; Interactive 3D Studio&lt;/a&gt;&lt;/strong&gt; - complete with a &lt;strong&gt;live browser-based 3D Biomolecular &amp;amp; Variant WebGL Sandbox&lt;/strong&gt;, a &lt;strong&gt;zero-dependency PEP 723 3D protein + PAE generator&lt;/strong&gt;, and a production &lt;strong&gt;&lt;code&gt;bio-structural-qc&lt;/code&gt; custom plugin&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Try the Live 3D Biomolecular &amp;amp; MCP Sidecar Studio in Your Browser
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://robinamirbahar.github.io/antigravity-science-plugin-cookbook/" rel="noopener noreferrer"&gt;Launch the Interactive 3D Biomolecular &amp;amp; Variant WebGL Studio (&lt;code&gt;index.html&lt;/code&gt;)&lt;/a&gt;&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Explore 3D C-alpha backbones &amp;amp; non-covalent contact networks for &lt;strong&gt;TP53 (&lt;code&gt;AF-P04637&lt;/code&gt;)&lt;/strong&gt;, &lt;strong&gt;Crambin (&lt;code&gt;1CRN&lt;/code&gt;)&lt;/strong&gt;, and &lt;strong&gt;EGFR Kinase + Gefitinib (&lt;code&gt;CHEMBL203&lt;/code&gt;)&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Click any 3D residue sphere via raycasting to trigger live &lt;strong&gt;&lt;code&gt;annotate_region&lt;/code&gt;&lt;/strong&gt; MCP tool calls, inspect &lt;strong&gt;AlphaFold pLDDT&lt;/strong&gt; &amp;amp; &lt;strong&gt;AlphaGenome Variant Impact (AVI)&lt;/strong&gt; scores, upload your own &lt;code&gt;.pdb&lt;/code&gt;/&lt;code&gt;.cif&lt;/code&gt; files, or run the interactive &lt;strong&gt;Aeneas Latin Epigraphy&lt;/strong&gt; restoration demo!&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://github.com/RobinaMirbahar/antigravity-science-plugin-cookbook" rel="noopener noreferrer"&gt;Full Source Code &amp;amp; &lt;code&gt;bio-structural-qc&lt;/code&gt; Plugin on GitHub (&lt;code&gt;RobinaMirbahar/antigravity-science-plugin-cookbook&lt;/code&gt;)&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  1. The Antigravity Customization Architecture &amp;amp; Context Economics
&lt;/h2&gt;

&lt;p&gt;Why can the Science plugin bundle &lt;strong&gt;40 complex scientific skills&lt;/strong&gt; and a &lt;strong&gt;9-tool 3D WebGL MCP server&lt;/strong&gt; without slowing down everyday coding turns? Because Antigravity strictly separates &lt;strong&gt;always-on behavioral guardrails&lt;/strong&gt; from &lt;strong&gt;on-demand procedural execution&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%2F9x5bla4tv75z487hg4nu.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%2F9x5bla4tv75z487hg4nu.png" alt="Antigravity Plugin &amp;amp; Customization Architecture" width="800" height="370"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The 5 Customization Primitives &amp;amp; Their Token Budgets
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Primitive&lt;/th&gt;
&lt;th&gt;Config File / Path&lt;/th&gt;
&lt;th&gt;Loading Behavior&lt;/th&gt;
&lt;th&gt;Token Budget &amp;amp; Engineering Role&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Rules&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;GEMINI.md&lt;/code&gt;, &lt;code&gt;AGENTS.md&lt;/code&gt;, &lt;code&gt;rules/AGENTS.md&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Always-On&lt;/strong&gt; (within directory or active plugin scope)&lt;/td&gt;
&lt;td&gt;Contextual rules loaded automatically for their active workspace or plugin scope, deduplicated by resolved file path.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Skills&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;skills/&amp;lt;name&amp;gt;/SKILL.md&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Progressive Disclosure&lt;/strong&gt; (On-Demand)&lt;/td&gt;
&lt;td&gt;Only the YAML &lt;code&gt;name&lt;/code&gt; and &lt;code&gt;description&lt;/code&gt; (~40-80 tokens) are injected into the system prompt. The full &lt;code&gt;SKILL.md&lt;/code&gt;  and &lt;code&gt;references/&lt;/code&gt; are read &lt;em&gt;only&lt;/em&gt; when activated.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Plugins&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;plugins/&amp;lt;dir&amp;gt;/plugin.json&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Atomic Bundle&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Namespaces and toggles related &lt;code&gt;skills/&lt;/code&gt;, &lt;code&gt;rules/&lt;/code&gt;, &lt;code&gt;hooks.json&lt;/code&gt;, &lt;code&gt;mcp_config.json&lt;/code&gt;, and &lt;code&gt;sidecars/&lt;/code&gt; as a single unit.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Hooks&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;hooks.json&lt;/code&gt; (at plugin or &lt;code&gt;.agents/&lt;/code&gt; root)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Lifecycle Event Triggers&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Intercepts &lt;code&gt;SessionStart&lt;/code&gt;, &lt;code&gt;PreInvocation&lt;/code&gt;, &lt;code&gt;PreToolUse&lt;/code&gt;, &lt;code&gt;PostToolUse&lt;/code&gt;, &lt;code&gt;PostInvocation&lt;/code&gt;, and &lt;code&gt;Stop&lt;/code&gt; to run shell validators, audit loggers, or linters.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;MCP &amp;amp; Sidecars&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;mcp_config.json&lt;/code&gt; + &lt;code&gt;sidecars/&amp;lt;name&amp;gt;/sidecar.json&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Tool + UI Integration&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Connects local (&lt;code&gt;stdio&lt;/code&gt;) or remote (&lt;code&gt;Streamable HTTP&lt;/code&gt;) tool servers (&lt;code&gt;mcp_config.json&lt;/code&gt;) and manages persistent background sidecar processes (&lt;code&gt;sidecar.json&lt;/code&gt;).&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  2. Inside the Open-Source &lt;code&gt;google-deepmind/science-skills&lt;/code&gt; Repository (&lt;code&gt;v1.3.1&lt;/code&gt;)
&lt;/h2&gt;

&lt;p&gt;You can enable the Science bundle directly in Google Antigravity (&lt;code&gt;Customizations &amp;gt; Build with Google &amp;gt; Science &amp;gt; Add&lt;/code&gt;) or install it via &lt;code&gt;npx skills add google-deepmind/science-skills/&lt;/code&gt; from &lt;strong&gt;&lt;a href="https://github.com/google-deepmind/science-skills" rel="noopener noreferrer"&gt;github.com/google-deepmind/science-skills&lt;/a&gt;&lt;/strong&gt;. Look at how cleanly &lt;code&gt;plugin.json&lt;/code&gt; and the 40 open-source skills are organized:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;google-deepmind/science-skills/ (installed at ~/.gemini/config/plugins/science/)
├── plugin.json                                  # Bundle manifest (name, description, $schema)
├── LICENSE                                      # Apache 2.0 &amp;amp; CC-BY 4.0 Open-Source Licenses
├── README.md                                    # User-facing setup &amp;amp; documentation
├── SKILL_LICENSES.md                            # Third-party database attribution &amp;amp; terms
└── skills/                                      # 40 Progressive-Disclosure Scientific Skills
    ├── alphafold_database_fetch_and_analyze/    # pLDDT &amp;amp; sliding-window PAE domain heuristics
    ├── alphagenome_atlas_website_links/         # Deep-links to AlphaGenome Atlas
    ├── alphagenome_single_variant_analysis/     # RNA-seq, DNASE, ChIP &amp;amp; splicing effects
    ├── alphagenome_variant_impact_score/        # AVI scoring, VCF annotation, GENCODE v46 GTF
    ├── chembl_database/                         # Bioactivity (IC50/Ki), targets, drug mechanisms
    ├── clinical_trials_database/                # ClinicalTrials.gov APIv2 queries
    ├── clinvar_database/                        # Pathogenicity &amp;amp; clinical review status
    ├── credentials/                             # Zero-leak .env verification protocol
    ├── dbsnp_database/                          # rsID &amp;lt;-&amp;gt; GRCh38 VCF/HGVS resolution
    ├── embl_ebi_ols/                            # 250+ biomedical ontologies (GO, HP, DOID)
    ├── encode_ccres_database/                   # ENCODE SCREEN GraphQL &amp;amp; cis-regulatory elements
    ├── ensembl_database/                        # Gene/transcript lookup, sequences &amp;amp; VEP
    ├── foldseek_structural_search/              # 3D structure similarity search (.cif/.pdb)
    ├── gnomad_database/                         # Allele frequencies &amp;amp; gene constraint (pLI/LOEUF)
    ├── gtex_database/                           # Tissue-specific RNA expression &amp;amp; eQTLs
    ├── human_protein_atlas_database/            # Spatial &amp;amp; tissue protein expression
    ├── interpro_database/                       # Protein domains, families &amp;amp; InterPro-N
    ├── jaspar_database/                         # TF binding profiles (PFMs/PWMs)
    ├── literature_search_arxiv/                 # arXiv preprints &amp;amp; full-text extraction
    ├── literature_search_biorxiv/               # bioRxiv / medRxiv narrow-window search
    ├── literature_search_europepmc/             # Europe PMC XML/PDF &amp;amp; citation graphs
    ├── literature_search_openalex/              # Bibliometrics, citation counts &amp;amp; OA PDFs
    ├── ncbi_sequence_fetch/                     # NCBI E-utilities nucleotide/protein fetch
    ├── openfda_database/                        # 28 FDA endpoints (adverse events, 510k, NDC)
    ├── opentargets_database/                    # Target-disease associations &amp;amp; tractability
    ├── pdb_database/                            # Experimental 3D structures from RCSB PDB
    ├── predictingthepast/                       # Aeneas (Latin) &amp;amp; Ithaca (Ancient Greek) epigraphy
    ├── protein_sequence_msa/                    # EBI Clustal Omega multiple sequence alignment
    ├── protein_sequence_similarity_search/      # MMseqs2 (fast) &amp;amp; BLAST homology search
    ├── pubchem_database/                        # SMILES/CID chemical properties &amp;amp; substructures
    ├── pubmed_database/                         # NCBI PubMed + PMC BioC full-text linking
    ├── pymol/                                   # Headless PyMOL rendering &amp;amp; structural superposition
    ├── quickgo_database/                        # Gene Ontology &amp;amp; ECO evidence mapping
    ├── reactome_database/                       # Pathway enrichment &amp;amp; reaction participants
    ├── string_database/                         # Protein-protein interaction (PPI) networks
    ├── ucsc_conservation_and_tfbs/              # phyloP, phastCons &amp;amp; ENCODE/JASPAR/ReMap TFBS
    ├── unibind_database/                        # Experimentally validated direct TF-DNA binding
    ├── uniprot_database/                        # UniProtKB/UniParc/UniRef metadata &amp;amp; sequences
    ├── uv/                                      # Prerequisite uv environment bootstrapper
    └── workflow_skill_creator/                  # Interactive distiller: turns chat workflows into skills
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  3. Five Production Engineering Patterns Inside the Science Plugin
&lt;/h2&gt;

&lt;p&gt;While inspecting the source files across all 40 skills, five engineering patterns stood out that every Google Cloud and agentic AI builder can adopt.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pattern 1: Always-On Behavioral Routing via &lt;code&gt;rules/AGENTS.md&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;As documented in the public &lt;strong&gt;&lt;a href="https://antigravity.google/docs/rules" rel="noopener noreferrer"&gt;Antigravity Rules Guide (&lt;code&gt;antigravity.google/docs/rules&lt;/code&gt;)&lt;/a&gt;&lt;/strong&gt;, rules define persistent coding standards and architectural constraints (&lt;code&gt;always_on&lt;/code&gt;, &lt;code&gt;model_decision&lt;/code&gt;, &lt;code&gt;glob&lt;/code&gt;, or &lt;code&gt;manual&lt;/code&gt;) that automatically apply within their configured workspace or plugin scope.&lt;/p&gt;

&lt;p&gt;In my custom &lt;code&gt;bio-structural-qc&lt;/code&gt; plugin (&lt;code&gt;plugins/bio-structural-qc/rules/AGENTS.md&lt;/code&gt;), I use a compact &lt;code&gt;AGENTS.md&lt;/code&gt; rule so the agent automatically audits 3D coordinate files (&lt;code&gt;.pdb&lt;/code&gt;, &lt;code&gt;.cif&lt;/code&gt;, &lt;code&gt;.mmcif&lt;/code&gt;) and warns about low-confidence disordered regions before running downstream structural searches or headless PyMOL renders:&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;# Biomolecular Structure QC Gate&lt;/span&gt;

Whenever a workflow downloads or modifies a 3D coordinate file (&lt;span class="sb"&gt;`.pdb`&lt;/span&gt;, &lt;span class="sb"&gt;`.cif`&lt;/span&gt;, or &lt;span class="sb"&gt;`.mmcif`&lt;/span&gt;) for downstream structural analysis, homology search, or variant mapping:
&lt;span class="p"&gt;
1.&lt;/span&gt; &lt;span class="gs"&gt;**Mandatory QC Audit**&lt;/span&gt;: Run the &lt;span class="sb"&gt;`structure-qc-audit`&lt;/span&gt; skill on the coordinate file before passing it to downstream modeling tools.
&lt;span class="p"&gt;2.&lt;/span&gt; &lt;span class="gs"&gt;**Disorder Warning**&lt;/span&gt;: If more than 30% of alpha-carbon (&lt;span class="sb"&gt;`CA`&lt;/span&gt;) atoms have a B-factor / pLDDT score below &lt;span class="sb"&gt;`50.0`&lt;/span&gt;, explicitly warn the user about disordered or low-confidence regions and report the high-confidence domain boundaries (&lt;span class="sb"&gt;`pLDDT &amp;gt;= 70`&lt;/span&gt;).
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Pattern 2: Zero-Pollution Python Micro-Environments (&lt;code&gt;uv&lt;/code&gt; + PEP 723 + Sliding-Window PAE Math)
&lt;/h3&gt;

&lt;p&gt;Running global &lt;code&gt;pip install&lt;/code&gt; inside a user's repository breaks virtual environments. Instead, every Science skill uses &lt;code&gt;uv run&lt;/code&gt; with &lt;strong&gt;PEP 723 inline script metadata (&lt;code&gt;# /// script&lt;/code&gt;)&lt;/strong&gt; and enforces rate limits and mathematical heuristics inside deterministic Python scripts.&lt;/p&gt;

&lt;p&gt;For example, in &lt;code&gt;skills/alphafold_database_fetch_and_analyze/scripts/&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;fetch_structure.py&lt;/code&gt; uses &lt;code&gt;polite-http&lt;/code&gt; with a hard &lt;code&gt;qps=1.0&lt;/code&gt; rate limit (&lt;code&gt;CLIENT = http_client.HttpClient("https://alphafold.ebi.ac.uk", qps=1.0)&lt;/code&gt;) and automatically falls back to the longest isoform for massive proteins (&lt;code&gt;&amp;gt; 2,700&lt;/code&gt; amino acids like Dystrophin).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;analyze_pae.py&lt;/code&gt; forbids the LLM from guessing domain boundaries by running a &lt;strong&gt;20-residue sliding-window Predicted Aligned Error (PAE) clustering algorithm&lt;/strong&gt; (&lt;code&gt;distance_cutoff=7.0 Å&lt;/code&gt;, &lt;code&gt;min_domain_size=40&lt;/code&gt;, &lt;code&gt;merge_cutoff=15.0 Å&lt;/code&gt;):
&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="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Analyzes Predicted Aligned Error (PAE) and detects domain boundaries.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

&lt;span class="c1"&gt;# /// script
# requires-python = "&amp;gt;=3.10"
# dependencies = []
# ///
&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;find_sub_domains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pae_matrix&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;distance_cutoff&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;7.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;min_domain_size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Identifies structurally independent sub-domains based on the PAE matrix.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;n_res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pae_matrix&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;domains&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;current_domain&lt;/span&gt; &lt;span class="o"&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;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n_res&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;current_domain&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;current_domain&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;continue&lt;/span&gt;

        &lt;span class="n"&gt;window_size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;current_domain&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="n"&gt;recent_res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;current_domain&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;window_size&lt;/span&gt;&lt;span class="p"&gt;:]&lt;/span&gt;
        &lt;span class="n"&gt;pae_sum&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pae_matrix&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;pae_matrix&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;recent_res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;avg_pae&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pae_sum&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;2.0&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;window_size&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;avg_pae&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;distance_cutoff&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;current_domain&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;current_domain&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;min_domain_size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;domains&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;current_domain&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;current_domain&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;current_domain&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;min_domain_size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;domains&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;current_domain&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="n"&gt;comp&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="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;comp&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="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="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;comp&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;domains&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Pattern 3: The Zero-Leak Credential Protocol (&lt;code&gt;skills/credentials/SKILL.md&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;Genomic and literature APIs like &lt;strong&gt;AlphaGenome&lt;/strong&gt; (&lt;code&gt;ALPHAGENOME_API_KEY&lt;/code&gt;) require secret keys. If an agent asks a user to paste their API key into the chat - or runs &lt;code&gt;cat ~/.env&lt;/code&gt; - that secret is permanently recorded in the conversation transcript and model context.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;credentials&lt;/code&gt; skill solves this with a strict &lt;strong&gt;Zero-Leak Protocol&lt;/strong&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Silent Exit-Code Verification:&lt;/strong&gt; The agent checks whether the variable exists in &lt;code&gt;~/.env&lt;/code&gt; using &lt;code&gt;grep -sq&lt;/code&gt; (quiet + suppress errors), reading &lt;em&gt;only&lt;/em&gt; the &lt;code&gt;0&lt;/code&gt; vs. non-zero exit code:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-sq&lt;/span&gt; &lt;span class="s2"&gt;"^ALPHAGENOME_API_KEY="&lt;/span&gt; ~/.env
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Hidden Terminal Prompting (&lt;code&gt;read -s&lt;/code&gt;):&lt;/strong&gt; If missing, the agent stops immediately and outputs a terminal command for the user to run locally where keystrokes are hidden (&lt;code&gt;read -s&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s2"&gt;"Enter ALPHAGENOME_API_KEY (typing hidden): "&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;read&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; val &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"ALPHAGENOME_API_KEY=&lt;/span&gt;&lt;span class="nv"&gt;$val&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&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;/.env"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Saved."&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Internal &lt;code&gt;dotenv&lt;/code&gt; Ingestion:&lt;/strong&gt; Helper scripts load &lt;code&gt;~/.env&lt;/code&gt; internally via &lt;code&gt;dotenv&lt;/code&gt;, so the key never appears in command-line flags or stdout.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;h3&gt;
  
  
  Pattern 4: Background Sidecars (&lt;code&gt;sidecar.json&lt;/code&gt;) &amp;amp; Custom 3D WebGL / MCP Tool Servers (&lt;code&gt;mcp_config.json&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;As documented in the public &lt;strong&gt;&lt;a href="https://antigravity.google/docs/sidecars" rel="noopener noreferrer"&gt;Antigravity Sidecars Guide (&lt;code&gt;antigravity.google/docs/sidecars&lt;/code&gt;)&lt;/a&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;a href="https://antigravity.google/docs/mcp" rel="noopener noreferrer"&gt;MCP Guide (&lt;code&gt;antigravity.google/docs/mcp&lt;/code&gt;)&lt;/a&gt;&lt;/strong&gt;, Antigravity lets plugins pair &lt;strong&gt;Model Context Protocol (&lt;code&gt;mcp_config.json&lt;/code&gt;)&lt;/strong&gt; tool servers with managed background &lt;strong&gt;Sidecar processes (&lt;code&gt;sidecar.json&lt;/code&gt;)&lt;/strong&gt; that support &lt;code&gt;command&lt;/code&gt;, &lt;code&gt;builtin&lt;/code&gt; (&lt;code&gt;schedule&lt;/code&gt;), &lt;code&gt;args&lt;/code&gt;, &lt;code&gt;restart_policy&lt;/code&gt; (&lt;code&gt;always&lt;/code&gt;, &lt;code&gt;on-failure&lt;/code&gt;, &lt;code&gt;never&lt;/code&gt;), &lt;code&gt;description&lt;/code&gt;, &lt;code&gt;env&lt;/code&gt;, and &lt;code&gt;display_name&lt;/code&gt;, plus programmatic interaction via &lt;code&gt;agentapi&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In my open-source &lt;strong&gt;&lt;a href="https://github.com/RobinaMirbahar/antigravity-science-plugin-cookbook" rel="noopener noreferrer"&gt;Antigravity Science Plugin Cookbook&lt;/a&gt;&lt;/strong&gt;, I pair a zero-dependency Python Stdio MCP Server (&lt;code&gt;plugins/genomics-variant-mcp/mcp_config.json&lt;/code&gt;) with a documented background Sidecar worker (&lt;code&gt;sidecar.json&lt;/code&gt;) and my browser-based &lt;strong&gt;3D PDBe Mol* / WebGL Biomolecular Studio (&lt;code&gt;index.html&lt;/code&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%2Fkd86102x1sscvtox7a2o.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%2Fkd86102x1sscvtox7a2o.png" alt="End-to-End 3D Structural Triage Sequence" width="800" height="330"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here are the two standard configuration files documented in &lt;code&gt;antigravity.google/docs/mcp&lt;/code&gt; and &lt;code&gt;antigravity.google/docs/sidecars&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;mcp_config.json&lt;/code&gt; (connecting a local Stdio MCP server at the plugin root):&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&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;"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;"genomics_variant_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;"uv"&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="s2"&gt;"run"&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/variant_mcp_server.py"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"timeoutSeconds"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;180&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;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;sidecars/qc_monitor/sidecar.json&lt;/code&gt; (configuring a managed background sidecar process per &lt;code&gt;antigravity.google/docs/sidecars&lt;/code&gt;):&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&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;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Background 3D structure QC &amp;amp; artifact monitor"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"display_name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Structure QC Sidecar"&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;"uv"&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="s2"&gt;"run"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"worker.py"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"restart_policy"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"on-failure"&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;h3&gt;
  
  
  Pattern 5: Domain-Specific Guardrails - From Clinical Genetics (&lt;code&gt;AlphaGenome&lt;/code&gt;) to Ancient Epigraphy (&lt;code&gt;Aeneas&lt;/code&gt; &amp;amp; &lt;code&gt;Ithaca&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;Two of the most fascinating skills in the bundle demonstrate how &lt;code&gt;SKILL.md&lt;/code&gt; enforces domain-specific scientific rigor:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;alphagenome-variant-impact-score&lt;/code&gt; (Strict Molecular Framing + Context-Overflow Protection):&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Clinical Safety Gate:&lt;/strong&gt; Explicitly forbids extrapolating high AlphaGenome Variant Impact (AVI) scores into clinical diagnoses or patient prognosis, restricting outputs to molecular mechanisms (splicing disruption, chromatin accessibility, TF binding, or GENCODE v46 transcript coordinates).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stdout Overflow Guard:&lt;/strong&gt; Warns the agent that &lt;code&gt;--include_track_info --format json&lt;/code&gt; emits &lt;code&gt;~3.9 KB&lt;/code&gt; per variant, requiring direct file redirection (&lt;code&gt;-o query_results.json&lt;/code&gt;) whenever querying &lt;code&gt;&amp;gt; 3&lt;/code&gt; variants so stdout never floods the context window.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;predictingthepast&lt;/code&gt; (Ancient Latin &amp;amp; Greek Epigraphy with DeepMind's Aeneas &amp;amp; Ithaca):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Restores damaged ancient inscriptions, attributes geographical province + chronological date ranges, and finds parallel inscriptions using special gap syntax (&lt;code&gt;?&lt;/code&gt; for a single missing character, &lt;code&gt;#&lt;/code&gt; for an unknown-length damaged gap):
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt; uv run scripts/preprocess.py &lt;span class="nt"&gt;--language&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;latin &lt;span class="nt"&gt;--input&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"imp caesar divi f ???????? cos xi"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Enforces a &lt;strong&gt;Self-Contained Epigraphy Rule&lt;/strong&gt;: forbids the agent from using web search to "cheat" or override the neural restoration probabilities returned by Aeneas/Ithaca.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  4. Five End-to-End Multi-Skill Use Cases Across the 40 Science Skills
&lt;/h2&gt;

&lt;p&gt;Because all 40 skills share the conversation's artifact directory, Antigravity can chain multiple domain-specific CLI scripts and MCP sidecars in a single research session.&lt;/p&gt;

&lt;p&gt;I included a runnable benchmark suite in &lt;a href="https://github.com/RobinaMirbahar/antigravity-science-plugin-cookbook/blob/main/examples/multi_domain_science_use_cases.py" rel="noopener noreferrer"&gt;&lt;code&gt;examples/multi_domain_science_use_cases.py&lt;/code&gt;&lt;/a&gt; (&lt;code&gt;uv run examples/multi_domain_science_use_cases.py&lt;/code&gt;) that executes and scores all five multi-skill pipelines below:&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%2Fd2x46gor91ikuata8m5d.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%2Fd2x46gor91ikuata8m5d.png" alt="5 End-to-End Multi-Skill Pipelines Scorecard" width="800" height="355"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Use Case 1: Precision Oncology &amp;amp; 3D Pocket Triage (&lt;code&gt;ClinVar&lt;/code&gt; → &lt;code&gt;gnomAD&lt;/code&gt; → &lt;code&gt;AlphaFold&lt;/code&gt; → &lt;code&gt;ChEMBL&lt;/code&gt; → &lt;code&gt;PyMOL / 3D WebGL Studio&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Scenario:&lt;/strong&gt; A translational oncology team wants to evaluate an &lt;strong&gt;EGFR L858R&lt;/strong&gt; (&lt;code&gt;rs121434568&lt;/code&gt;, &lt;code&gt;chr7:55191822:T&amp;gt;G&lt;/code&gt;) driver mutation, verify gene loss-of-function constraint, inspect 3D active-site confidence, rank nanomolar kinase inhibitors, and highlight the pocket in 3D.&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;# 1. Check allele rarity &amp;amp; gene constraint (pLI / LOEUF) in gnomAD&lt;/span&gt;
uv run ~/.gemini/config/plugins/science/skills/gnomad_database/scripts/get_gene_constraint.py &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--gene&lt;/span&gt; EGFR &lt;span class="nt"&gt;--output&lt;/span&gt; ./artifacts/egfr_constraint.json

&lt;span class="c"&gt;# 2. Fetch AlphaFold 3D structure (P00533) &amp;amp; audit pLDDT + PAE domains&lt;/span&gt;
uv run ~/.gemini/config/plugins/science/skills/alphafold_database_fetch_and_analyze/scripts/fetch_structure.py &lt;span class="se"&gt;\&lt;/span&gt;
  P00533 &lt;span class="nt"&gt;-o&lt;/span&gt; ./artifacts/P00533/
uv run ~/.gemini/config/plugins/science/skills/alphafold_database_fetch_and_analyze/scripts/analyze_pae.py &lt;span class="se"&gt;\&lt;/span&gt;
  ./artifacts/P00533/AF-P00533-F1-predicted_aligned_error_v6.json

&lt;span class="c"&gt;# 3. Screen ChEMBL for EGFR (CHEMBL203) bioactivities &amp;amp; download 3D SDF ligands&lt;/span&gt;
uv run ~/.gemini/config/plugins/science/skills/chembl_database/scripts/chembl_api.py &lt;span class="se"&gt;\&lt;/span&gt;
  activity &lt;span class="nt"&gt;--search&lt;/span&gt; &lt;span class="s2"&gt;"EGFR"&lt;/span&gt; &lt;span class="nt"&gt;--limit&lt;/span&gt; 10 &lt;span class="nt"&gt;--output&lt;/span&gt; ./artifacts/egfr_chembl_ic50.json
uv run ~/.gemini/config/plugins/science/skills/chembl_database/scripts/chembl_api.py &lt;span class="se"&gt;\&lt;/span&gt;
  molecule &lt;span class="nt"&gt;--id&lt;/span&gt; CHEMBL939 &lt;span class="nt"&gt;--dl_format&lt;/span&gt; sdf &lt;span class="nt"&gt;--output&lt;/span&gt; ./artifacts/gefitinib.sdf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, the agent renders the 3D kinase pocket (&lt;code&gt;residues 855-862&lt;/code&gt; in chain &lt;code&gt;A&lt;/code&gt;) using headless PyMOL (&lt;code&gt;pymol&lt;/code&gt; skill) or my interactive &lt;strong&gt;&lt;a href="https://robinamirbahar.github.io/antigravity-science-plugin-cookbook/" rel="noopener noreferrer"&gt;3D Biomolecular &amp;amp; Variant WebGL Studio (&lt;code&gt;index.html&lt;/code&gt;)&lt;/a&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%2Ffk5ndpa0eol9t5hrhyij.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%2Ffk5ndpa0eol9t5hrhyij.png" alt="Use Case 1 - Precision Oncology &amp;amp; 3D Kinase Pocket Triage" width="799" height="288"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Use Case 2: Non-Coding GWAS Enhancer Variant Triage (&lt;code&gt;AlphaGenome&lt;/code&gt; → &lt;code&gt;UCSC phyloP&lt;/code&gt; → &lt;code&gt;ENCODE cCRE&lt;/code&gt; → &lt;code&gt;JASPAR&lt;/code&gt; → &lt;code&gt;GTEx&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Scenario:&lt;/strong&gt; Over 90% of GWAS risk loci fall in non-coding DNA. Suppose you are investigating &lt;code&gt;chr1:109274968:G&amp;gt;T&lt;/code&gt; (&lt;code&gt;rs12740374&lt;/code&gt; at the &lt;em&gt;SORT1&lt;/em&gt; 1p13 locus) and want to know &lt;em&gt;how&lt;/em&gt; it alters gene regulation across human tissues without hallucinating clinical diagnoses:&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;# 1. Score variant impact across 18 biological modalities + GENCODE v46 coordinates&lt;/span&gt;
uv run ~/.gemini/config/plugins/science/skills/alphagenome_variant_impact_score/scripts/alphagenome_atlas_avi.py &lt;span class="se"&gt;\&lt;/span&gt;
  query &lt;span class="s2"&gt;"chr1:109274968:G&amp;gt;T"&lt;/span&gt; &lt;span class="nt"&gt;--include_track_info&lt;/span&gt; &lt;span class="nt"&gt;--format&lt;/span&gt; json &lt;span class="nt"&gt;-o&lt;/span&gt; ./artifacts/sort1_avi.json

&lt;span class="c"&gt;# 2. Check 100-vertebrate evolutionary constraint (phyloP100way &amp;amp; phastCons100way)&lt;/span&gt;
uv run ~/.gemini/config/plugins/science/skills/ucsc_conservation_and_tfbs/scripts/get_conservation.py &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--coordinates&lt;/span&gt; &lt;span class="s2"&gt;"chr1:109274968"&lt;/span&gt; &lt;span class="nt"&gt;--output&lt;/span&gt; ./artifacts/sort1_phylop.json

&lt;span class="c"&gt;# 3. Fetch Transcription Factor Position Weight Matrices (PWMs) from JASPAR (CEBPA)&lt;/span&gt;
uv run ~/.gemini/config/plugins/science/skills/jaspar_database/scripts/jaspar_cli.py &lt;span class="se"&gt;\&lt;/span&gt;
  search &lt;span class="nt"&gt;--query&lt;/span&gt; &lt;span class="s2"&gt;"CEBPA"&lt;/span&gt; &lt;span class="nt"&gt;--output&lt;/span&gt; ./artifacts/cebpa_jaspar.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Engineering Guardrail in Action:&lt;/strong&gt; The &lt;code&gt;alphagenome-variant-impact-score&lt;/code&gt; skill enforces that &lt;code&gt;--include_track_info&lt;/code&gt; outputs (&lt;code&gt;~3.9 KB/variant&lt;/code&gt;) are redirected via &lt;code&gt;-o&lt;/code&gt; and framed strictly in terms of molecular mechanisms (&lt;code&gt;CEBPA&lt;/code&gt; binding site creation + liver RNA-seq eQTL shift):&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%2Fwfc326ldwdwonivym7jd.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%2Fwfc326ldwdwonivym7jd.png" alt="Use Case 2 - Non-Coding GWAS Enhancer Variant Triage" width="799" height="288"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Use Case 3: Dark-Proteome Enzyme Discovery (&lt;code&gt;AlphaFold&lt;/code&gt; → &lt;code&gt;Foldseek 3D Search&lt;/code&gt; → &lt;code&gt;InterPro&lt;/code&gt; → &lt;code&gt;Clustal Omega MSA&lt;/code&gt; → &lt;code&gt;Headless PyMOL&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Scenario:&lt;/strong&gt; A protein engineering group wants to discover novel thermostable plastic-degrading &lt;strong&gt;PETase&lt;/strong&gt; homologs hidden in environmental metagenomes where sequence identity is below 25% (the "twilight zone" where BLAST fails, but 3D fold geometry is conserved):&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;# 1. Search the 3D coordinate file against Foldseek's metagenomic &amp;amp; AlphaFold databases&lt;/span&gt;
uv run ~/.gemini/config/plugins/science/skills/foldseek_structural_search/scripts/search.py &lt;span class="se"&gt;\&lt;/span&gt;
  ./artifacts/PETase_AF.cif &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--databases&lt;/span&gt; afdb50,mgnify_esm30,pdb100,cath50 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-o&lt;/span&gt; ./artifacts/petase_foldseek.json &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; ./artifacts/petase_foldseek_summary.md

&lt;span class="c"&gt;# 2. Align the top structural hits with EBI Clustal Omega to verify the Ser-Asp-His catalytic triad&lt;/span&gt;
uv run ~/.gemini/config/plugins/science/skills/protein_sequence_msa/scripts/clustalo.py &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--input&lt;/span&gt; ./artifacts/petase_homologs.fasta &lt;span class="nt"&gt;--output&lt;/span&gt; ./artifacts/petase_msa.aln
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Engineering Guardrail in Action:&lt;/strong&gt; Look at &lt;code&gt;foldseek-structural-search/SKILL.md&lt;/code&gt;:

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Strict Input Gate:&lt;/strong&gt; If the user only gives a gene name or sequence without a &lt;code&gt;.pdb&lt;/code&gt;/&lt;code&gt;.cif&lt;/code&gt; file, the skill &lt;strong&gt;halts immediately&lt;/strong&gt; and instructs the agent to fetch the 3D structure first.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Database Allowlist:&lt;/strong&gt; Enforces validation against the exact 9 supported Foldseek databases (&lt;code&gt;afdb50&lt;/code&gt;, &lt;code&gt;afdb-swissprot&lt;/code&gt;, &lt;code&gt;pdb100&lt;/code&gt;, &lt;code&gt;BFVD&lt;/code&gt;, &lt;code&gt;mgnify_esm30&lt;/code&gt;, &lt;code&gt;cath50&lt;/code&gt;, &lt;code&gt;gmgcl_id&lt;/code&gt;, &lt;code&gt;bfmd&lt;/code&gt;, &lt;code&gt;afdb-proteome&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Headless OSMesa PyMOL Superposition (&lt;code&gt;pymol&lt;/code&gt; skill):&lt;/strong&gt; When generating static publication figures alongside &lt;code&gt;.pse&lt;/code&gt; session files, the &lt;code&gt;pymol&lt;/code&gt; skill runs headless via &lt;code&gt;PYOPENGL_PLATFORM=osmesa&lt;/code&gt; and automatically checks &lt;code&gt;cmd.count_atoms("name CA") == cmd.count_atoms("all")&lt;/code&gt; so C-alpha-only traces still render as smooth cartoons!&lt;/li&gt;
&lt;/ol&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%2Fronuzwevbxaadrwrnfp5.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%2Fronuzwevbxaadrwrnfp5.png" alt="Use Case 3 - Dark-Proteome Enzyme Discovery with Foldseek" width="799" height="288"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Use Case 4: Clinical Trial Intelligence &amp;amp; Pharmacovigilance Audit (&lt;code&gt;OpenTargets&lt;/code&gt; → &lt;code&gt;ClinicalTrials.gov&lt;/code&gt; → &lt;code&gt;openFDA&lt;/code&gt; → &lt;code&gt;OpenAlex&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Scenario:&lt;/strong&gt; A clinical data science team wants to map all recruiting &lt;strong&gt;Phase 3 trials&lt;/strong&gt; for a target indication, inspect inclusion/exclusion criteria without overflowing the LLM context window, and audit real-world post-market adverse events across &lt;strong&gt;28 FDA endpoints&lt;/strong&gt;:&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;# 1. Query Open Targets for Phase 3+ candidates and target tractability&lt;/span&gt;
uv run ~/.gemini/config/plugins/science/skills/opentargets_database/scripts/query_opentargets.py &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--output&lt;/span&gt; ./artifacts/nsclc_drugs.json &lt;span class="nt"&gt;--limit&lt;/span&gt; 15 &lt;span class="se"&gt;\&lt;/span&gt;
  get-disease-drugs MONDO_0005090 &lt;span class="nt"&gt;--min-stage&lt;/span&gt; PHASE_3

&lt;span class="c"&gt;# 2. Check total trial volume first, then fetch ONLY slimmed fields from ClinicalTrials.gov APIv2&lt;/span&gt;
uv run ~/.gemini/config/plugins/science/skills/clinical_trials_database/scripts/clinical_trials_api.py &lt;span class="se"&gt;\&lt;/span&gt;
  search &lt;span class="nt"&gt;--condition&lt;/span&gt; &lt;span class="s2"&gt;"Non-Small Cell Lung Cancer"&lt;/span&gt; &lt;span class="nt"&gt;--status&lt;/span&gt; RECRUITING &lt;span class="nt"&gt;--phase&lt;/span&gt; PHASE3 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--count-total&lt;/span&gt; &lt;span class="nt"&gt;--fields&lt;/span&gt; NCTId,BriefTitle,OverallStatus,EligibilityCriteria &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--limit&lt;/span&gt; 10 &lt;span class="nt"&gt;--output&lt;/span&gt; ./artifacts/nsclc_phase3_trials.json

&lt;span class="c"&gt;# 3. Query openFDA Drug Adverse Events (FAERS) with automatic rate-limit protection&lt;/span&gt;
uv run ~/.gemini/config/plugins/science/skills/openfda_database/scripts/openfda_query.py &lt;span class="se"&gt;\&lt;/span&gt;
  count &lt;span class="nt"&gt;--category&lt;/span&gt; drug &lt;span class="nt"&gt;--endpoint&lt;/span&gt; event &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--search&lt;/span&gt; &lt;span class="s2"&gt;"patient.drug.medicinalproduct:osimertinib"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--count&lt;/span&gt; &lt;span class="s2"&gt;"patient.reaction.reactionmeddrapt.exact"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--limit&lt;/span&gt; 10 &lt;span class="nt"&gt;--output&lt;/span&gt; ./artifacts/osimertinib_faers_counts.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Engineering Guardrails in Action:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;ClinicalTrials.gov Context Projection (&lt;code&gt;--fields&lt;/code&gt;):&lt;/strong&gt; Full &lt;code&gt;protocolSection&lt;/code&gt; + &lt;code&gt;resultsSection&lt;/code&gt; trial JSON payloads can exceed 100 KB per study. &lt;code&gt;clinical-trials-database&lt;/code&gt; requires &lt;code&gt;--count-total&lt;/code&gt; first and shorthand &lt;code&gt;--fields&lt;/code&gt; projection (&lt;code&gt;NCTId,BriefTitle,OverallStatus&lt;/code&gt;), reducing payload size by &lt;code&gt;98.7%&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;openFDA Quota Escalation (&lt;code&gt;1,000&lt;/code&gt; → &lt;code&gt;1&lt;/code&gt; req/day):&lt;/strong&gt; &lt;code&gt;openfda-database&lt;/code&gt; warns that an autonomous agent can burn through the 1,000 keyless daily quota in a single session, triggering the &lt;strong&gt;&lt;code&gt;credentials&lt;/code&gt;&lt;/strong&gt; skill (&lt;code&gt;grep -sq "^FDA_API_KEY=" ~/.env&lt;/code&gt;) before running multi-query workflows:&lt;/li&gt;
&lt;/ul&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%2Fbn4k86c285tdioo4ja6f.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%2Fbn4k86c285tdioo4ja6f.png" alt="Use Case 4 - Clinical Trial Portfolio &amp;amp; openFDA FAERS Safety Audit" width="799" height="288"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Use Case 5: Systems Biology &amp;amp; Ancient Epigraphy (&lt;code&gt;STRING&lt;/code&gt; → &lt;code&gt;Reactome&lt;/code&gt; &amp;amp; DeepMind's &lt;code&gt;Aeneas&lt;/code&gt; / &lt;code&gt;Ithaca&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;Two more specialized workflows show how the Science plugin handles &lt;strong&gt;ambiguous biological identifiers&lt;/strong&gt; and &lt;strong&gt;digital humanities&lt;/strong&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Systems Biology Pathway Enrichment (&lt;code&gt;STRING&lt;/code&gt; + &lt;code&gt;Reactome&lt;/code&gt;):&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The &lt;code&gt;STRING&lt;/code&gt; "Never Assume Human" Rule:&lt;/strong&gt; Even if a user asks for &lt;code&gt;TP53&lt;/code&gt; or &lt;code&gt;BRCA1&lt;/code&gt; interaction partners, &lt;code&gt;string-database/SKILL.md&lt;/code&gt; strictly forbids defaulting to &lt;em&gt;Homo sapiens&lt;/em&gt; (&lt;code&gt;9606&lt;/code&gt;) if the species wasn't stated - requiring the agent to ask for the NCBI Taxon ID first, map symbols via &lt;code&gt;string_cli.py map&lt;/code&gt;, and then export pathway diagrams in &lt;code&gt;reactome-database&lt;/code&gt; (preferring specific sub-pathways like &lt;strong&gt;Cell Cycle, Mitotic&lt;/strong&gt; (&lt;code&gt;R-HSA-69278&lt;/code&gt;) over broad top-level nodes).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Restoring Damaged Roman &amp;amp; Greek Stone Inscriptions (&lt;code&gt;predictingthepast&lt;/code&gt;):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Powered by Google DeepMind's &lt;strong&gt;Aeneas&lt;/strong&gt; (Latin) and &lt;strong&gt;Ithaca&lt;/strong&gt; (Ancient Greek) models:
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt; &lt;span class="c"&gt;# Preprocess damaged Latin epigraphy (? = single missing character, # = unknown-length gap)&lt;/span&gt;
 uv run ~/.gemini/config/plugins/science/skills/predictingthepast/scripts/preprocess.py &lt;span class="se"&gt;\&lt;/span&gt;
   &lt;span class="nt"&gt;--language&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;latin &lt;span class="se"&gt;\&lt;/span&gt;
   &lt;span class="nt"&gt;--input&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"imp caesar divi f ???????? cos xi trib potest"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Returns ranked character restorations (&lt;code&gt;augustus&lt;/code&gt;, &lt;code&gt;96.4%&lt;/code&gt; confidence), geographical province attribution (&lt;em&gt;Latium et Campania&lt;/em&gt;), chronological dating (&lt;code&gt;23 BCE&lt;/code&gt;), and corpus parallels - while strictly blocking external web search so model probabilities remain unadulterated:&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%2F75pg4fkdew4h1efgbu1c.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%2F75pg4fkdew4h1efgbu1c.png" alt="Use Case 5 - Ancient Roman &amp;amp; Greek Epigraphy Restoration" width="799" height="288"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  5. Hands-On Cookbook: Build &amp;amp; Run the Custom &lt;code&gt;bio-structural-qc&lt;/code&gt; Plugin
&lt;/h2&gt;

&lt;p&gt;In the companion repository (&lt;strong&gt;&lt;a href="https://github.com/RobinaMirbahar/antigravity-science-plugin-cookbook" rel="noopener noreferrer"&gt;RobinaMirbahar/antigravity-science-plugin-cookbook&lt;/a&gt;&lt;/strong&gt;), I built a complete, installable custom plugin called &lt;strong&gt;&lt;code&gt;bio-structural-qc&lt;/code&gt;&lt;/strong&gt; plus a zero-dependency &lt;strong&gt;3D Protein + PAE Generator &amp;amp; SVG Dashboard (&lt;code&gt;examples/generate_3d_protein_pae_demo.py&lt;/code&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%2Fi0kztu71wvmticd037uc.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%2Fi0kztu71wvmticd037uc.png" alt="AlphaFold pLDDT Profile &amp;amp; PAE Domain Matrix" width="800" height="332"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Directory Structure of &lt;code&gt;bio-structural-qc&lt;/code&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;plugins/bio-structural-qc/
├── plugin.json                                    # Manifest &amp;amp; 3 starter prompts
├── hooks.json                                     # PostToolUse command reproducibility hook
├── assets/
│   └── logo.svg                                   # 128x128 high-contrast SVG icon
├── rules/
│   └── AGENTS.md                                  # Mandatory QC gate before docking/Foldseek
├── scripts/
│   └── log_reproducibility_audit.py               # Redacts secrets + hashes scripts &amp;amp; input files
└── skills/
    └── structure-qc-audit/
        ├── SKILL.md                               # Progressive-disclosure instructions
        └── scripts/
            └── audit_structure.py                 # PEP 723 C-alpha B-factor/pLDDT auditor
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  1. The Always-On QC Gate (&lt;code&gt;plugins/bio-structural-qc/rules/AGENTS.md&lt;/code&gt;)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gh"&gt;# Biomolecular Structure QC Gate&lt;/span&gt;

Whenever a workflow downloads or modifies a 3D coordinate file (&lt;span class="sb"&gt;`.pdb`&lt;/span&gt;, &lt;span class="sb"&gt;`.cif`&lt;/span&gt;, or &lt;span class="sb"&gt;`.mmcif`&lt;/span&gt;) for downstream structural analysis, homology search, or variant mapping:
&lt;span class="p"&gt;
1.&lt;/span&gt; &lt;span class="gs"&gt;**Mandatory QC Audit**&lt;/span&gt;: Run the &lt;span class="sb"&gt;`structure-qc-audit`&lt;/span&gt; skill on the coordinate file before passing it to downstream modeling tools.
&lt;span class="p"&gt;2.&lt;/span&gt; &lt;span class="gs"&gt;**Disorder Warning**&lt;/span&gt;: If more than 30% of alpha-carbon (&lt;span class="sb"&gt;`CA`&lt;/span&gt;) atoms have a B-factor / pLDDT score below &lt;span class="sb"&gt;`50.0`&lt;/span&gt;, explicitly warn the user about disordered or low-confidence regions and report the high-confidence domain boundaries (&lt;span class="sb"&gt;`pLDDT &amp;gt;= 70`&lt;/span&gt;) before rendering.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. The Zero-Dependency PEP 723 Structure Auditor (&lt;code&gt;audit_structure.py&lt;/code&gt;)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;#!/usr/bin/env python3
&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Audits PDB and mmCIF coordinate files for chain completeness and B-factor/pLDDT distribution.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

&lt;span class="c1"&gt;# /// script
# requires-python = "&amp;gt;=3.10"
# dependencies = []
# ///
&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;argparse&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;statistics&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;pathlib&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Path&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;parse_ca_bfactors&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filepath&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Path&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="n"&gt;chains&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="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;tuple&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;]]]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
    &lt;span class="n"&gt;ext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;filepath&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;suffix&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;with&lt;/span&gt; &lt;span class="n"&gt;filepath&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;encoding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;utf-8&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;replace&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;f&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;ext&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.pdb&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startswith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ATOM  &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;CA&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;chain_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;21&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;A&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
                &lt;span class="n"&gt;chains&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setdefault&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;chain_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[]).&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;26&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt; &lt;span class="nf"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;66&lt;/span&gt;&lt;span class="p"&gt;])))&lt;/span&gt;
            &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;ext&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.cif&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;.mmcif&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startswith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ATOM &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
                &lt;span class="n"&gt;parts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;parts&lt;/span&gt;&lt;span class="p"&gt;)&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="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;parts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;CA&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                    &lt;span class="n"&gt;chains&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setdefault&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;parts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[]).&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;parts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt; &lt;span class="nf"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;parts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="p"&gt;])))&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;chains&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Test both the 3D generator and the QC auditor in two commands using &lt;code&gt;uv run&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;git clone https://github.com/RobinaMirbahar/antigravity-science-plugin-cookbook.git
&lt;span class="nb"&gt;cd &lt;/span&gt;antigravity-science-plugin-cookbook

&lt;span class="c"&gt;# 1. Generate a 56-residue 3-domain 3D .pdb structure, PAE matrix JSON, and SVG dashboard&lt;/span&gt;
uv run examples/generate_3d_protein_pae_demo.py

&lt;span class="c"&gt;# 2. Audit both the synthetic multi-domain protein and the Crambin structure&lt;/span&gt;
uv run plugins/bio-structural-qc/skills/structure-qc-audit/scripts/audit_structure.py &lt;span class="se"&gt;\&lt;/span&gt;
  examples/generated_p53_demo/synthetic_p53_multidomain.pdb &lt;span class="se"&gt;\&lt;/span&gt;
  examples/sample_crambin_fragment.pdb
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&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="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"file"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"synthetic_p53_multidomain.pdb"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"PASS"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"total_ca_residues"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;56&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"overall_mean_score"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;82.11&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"overall_pct_low_lt_50"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;17.9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"chains"&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;"A"&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;"residue_count"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;56&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"mean_score"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;82.11&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"median_score"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;90.26&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"pct_high_confidence_ge_70"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;82.1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"pct_low_confidence_lt_50"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;17.9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"high_confidence_span"&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="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;56&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;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;h3&gt;
  
  
  3. Reproducibility Lifecycle Hook (&lt;code&gt;hooks.json&lt;/code&gt; &amp;amp; &lt;code&gt;log_reproducibility_audit.py&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;A bare timestamp log only tells you &lt;em&gt;when&lt;/em&gt; &lt;code&gt;run_command&lt;/code&gt; fired, not &lt;em&gt;what&lt;/em&gt; actually executed or which version of a script and input &lt;code&gt;.pdb&lt;/code&gt;/&lt;code&gt;.cif&lt;/code&gt; coordinates produced a scientific result. At the same time, logging raw shell commands is dangerous if an inline environment variable or &lt;code&gt;--api-key&lt;/code&gt; flag is present.&lt;/p&gt;

&lt;p&gt;Because Antigravity passes a structured JSON payload to every &lt;code&gt;PostToolUse&lt;/code&gt; hook over &lt;code&gt;stdin&lt;/code&gt; (&lt;code&gt;toolCall.args.CommandLine&lt;/code&gt;, &lt;code&gt;workspacePaths&lt;/code&gt;, &lt;code&gt;conversationId&lt;/code&gt;, &lt;code&gt;stepIdx&lt;/code&gt;), I wire &lt;code&gt;plugins/bio-structural-qc/hooks.json&lt;/code&gt; to a zero-dependency PEP 723 audit script (&lt;code&gt;plugins/bio-structural-qc/scripts/log_reproducibility_audit.py&lt;/code&gt;) that:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Redacts Secrets Before Logging:&lt;/strong&gt; Strips any environment variables matching &lt;code&gt;*KEY*&lt;/code&gt;, &lt;code&gt;*TOKEN*&lt;/code&gt;, &lt;code&gt;*SECRET*&lt;/code&gt;, &lt;code&gt;*PASS*&lt;/code&gt;, &lt;code&gt;*CRED*&lt;/code&gt;, or &lt;code&gt;*AUTH*&lt;/code&gt;, plus &lt;code&gt;Bearer&lt;/code&gt;/&lt;code&gt;Basic&lt;/code&gt; headers and &lt;code&gt;--api-key&lt;/code&gt;/&lt;code&gt;--token&lt;/code&gt; CLI flags.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Records Exact Script Versions &amp;amp; Git State:&lt;/strong&gt; Captures &lt;code&gt;git rev-parse --short HEAD&lt;/code&gt; (&lt;code&gt;+dirty&lt;/code&gt; if uncommitted changes exist) and computes a 16-character SHA-256 digest (&lt;code&gt;script_versions&lt;/code&gt;) for every executed &lt;code&gt;.py&lt;/code&gt; or &lt;code&gt;.sh&lt;/code&gt; script.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hashes All Referenced Input &amp;amp; Output Files:&lt;/strong&gt; Tokenizes the command line and computes SHA-256 digests (&lt;code&gt;file_hashes&lt;/code&gt;) for every referenced &lt;code&gt;.pdb&lt;/code&gt;, &lt;code&gt;.cif&lt;/code&gt;, &lt;code&gt;.mmcif&lt;/code&gt;, &lt;code&gt;.vcf&lt;/code&gt;, &lt;code&gt;.json&lt;/code&gt;, &lt;code&gt;.fasta&lt;/code&gt;, or &lt;code&gt;.sdf&lt;/code&gt; file.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Honors the &lt;code&gt;PostToolUse&lt;/code&gt; Stdout Contract:&lt;/strong&gt; Appends the JSONL record to &lt;code&gt;~/.gemini/qc_command_audit.jsonl&lt;/code&gt; and emits &lt;code&gt;{}&lt;/code&gt; on &lt;code&gt;stdout&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;plugins/bio-structural-qc/hooks.json&lt;/code&gt;:&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&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;"qc-command-audit-log"&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;"enabled"&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="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"PostToolUse"&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;"matcher"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"run_command"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"hooks"&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;"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;"command"&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;"uv run plugins/bio-structural-qc/scripts/log_reproducibility_audit.py"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"timeout"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;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="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;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;plugins/bio-structural-qc/scripts/log_reproducibility_audit.py&lt;/code&gt; (Core Redaction &amp;amp; Hashing Logic):&lt;/strong&gt;
&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="c1"&gt;#!/usr/bin/env python3
&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;PostToolUse reproducibility hook: logs redacted commands, script SHA-256 versions, and input file hashes.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

&lt;span class="c1"&gt;# /// script
# requires-python = "&amp;gt;=3.10"
# dependencies = []
# ///
&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;hashlib&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pathlib&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;shlex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;

&lt;span class="n"&gt;SECRET_PATTERNS&lt;/span&gt; &lt;span class="o"&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;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;\b([A-Za-z0-9_]*(?:KEY|TOKEN|SECRET|PASS|PASSWORD|CRED|AUTH)[A-Za-z0-9_]*)\s*=\s*(&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;]*&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;|\"[^\"]*\"|\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;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;I&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;\1=[REDACTED]&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;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;(Bearer|Basic)\s+[A-Za-z0-9._\-+/=]+&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;I&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;\1 [REDACTED]&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;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;(--(?:api[-_]?key|token|secret|password)|x-goog-api-key:|api-key:)\s*([=:]?\s*)(&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;]*&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;|\"[^\"]*\"|\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;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;I&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;\1\2[REDACTED]&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;TRACKED_EXTENSIONS&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;.py&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;.sh&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;.pdb&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;.cif&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;.mmcif&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;.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;.fasta&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;.fa&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;.aln&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;.sdf&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;.vcf&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;.gtf&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;.tsv&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;.csv&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;redact_secrets&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cmd&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;-&amp;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;for&lt;/span&gt; &lt;span class="n"&gt;pattern&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;repl&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;SECRET_PATTERNS&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;cmd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pattern&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;repl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;cmd&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;sha256_file&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;pathlib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Path&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;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;hashlib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sha256&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;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;rb&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;chunk&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;iter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;65536&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&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;sha256:&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hexdigest&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Verified Commands: Test Secret Redaction &amp;amp; Input File Hashing Locally
&lt;/h4&gt;

&lt;p&gt;You can verify both the built-in &lt;code&gt;--self-test&lt;/code&gt; mode and the live &lt;code&gt;stdin&lt;/code&gt; hook contract in two commands:&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;# 1. Run the built-in self-test (simulates an inline ALPHAGENOME_API_KEY + 2 PDB input files)&lt;/span&gt;
uv run plugins/bio-structural-qc/scripts/log_reproducibility_audit.py &lt;span class="nt"&gt;--self-test&lt;/span&gt;

&lt;span class="c"&gt;# 2. Simulate Antigravity's PostToolUse stdin payload and inspect ~/.gemini/qc_command_audit.jsonl&lt;/span&gt;
&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s1"&gt;'{"conversationId":"conv-demo","stepIdx":1,"toolCall":{"name":"run_command","args":{"CommandLine":"FDA_API_KEY=secret123 uv run plugins/bio-structural-qc/skills/structure-qc-audit/scripts/audit_structure.py examples/sample_crambin_fragment.pdb"} } }'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  | uv run plugins/bio-structural-qc/scripts/log_reproducibility_audit.py
&lt;span class="nb"&gt;tail&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; 1 ~/.gemini/qc_command_audit.jsonl
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Verified &lt;code&gt;--self-test&lt;/code&gt; output:&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;"timestamp_utc"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-10-24T19:27:00.315004+00:00"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"event"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"PostToolUse"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"tool"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"run_command"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"conversation_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;"conv-repro-demo-01"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"step_idx"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"git_revision"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"06fd7e9"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"redacted_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;"ALPHAGENOME_API_KEY=[REDACTED] uv run plugins/bio-structural-qc/skills/structure-qc-audit/scripts/audit_structure.py examples/generated_p53_demo/synthetic_p53_multidomain.pdb examples/sample_crambin_fragment.pdb"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"script_versions"&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;"plugins/bio-structural-qc/skills/structure-qc-audit/scripts/audit_structure.py"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sha256:b305f0ca720d7673"&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;"file_hashes"&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;"examples/generated_p53_demo/synthetic_p53_multidomain.pdb"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sha256:f929c693e8e2fbfa"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"examples/sample_crambin_fragment.pdb"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sha256:5ddc4bb4a2f0e889"&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;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"OK"&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;h3&gt;
  
  
  4. Interactive 1-Command Plugin Scaffolder &amp;amp; Loader Validator (&lt;code&gt;scaffold_custom_plugin.py&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;To make authoring and testing your own plugins effortless, I also included an interactive &lt;strong&gt;1-Command Plugin Scaffolder &amp;amp; Loader Validator&lt;/strong&gt; (&lt;a href="https://github.com/RobinaMirbahar/antigravity-science-plugin-cookbook/blob/main/examples/scaffold_custom_plugin.py" rel="noopener noreferrer"&gt;&lt;code&gt;examples/scaffold_custom_plugin.py&lt;/code&gt;&lt;/a&gt;) that:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Validates&lt;/strong&gt; any plugin directory against Antigravity's loader rules (&lt;code&gt;plugin.json&lt;/code&gt; manifest keys, relative logo path, concise &lt;code&gt;rules/AGENTS.md&lt;/code&gt; files, root &lt;code&gt;hooks.json&lt;/code&gt; placement, and &lt;code&gt;SKILL.md&lt;/code&gt; YAML frontmatter).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scaffolds&lt;/strong&gt; a complete new plugin bundle (&lt;code&gt;plugin.json&lt;/code&gt;, &lt;code&gt;assets/logo.svg&lt;/code&gt;, &lt;code&gt;rules/AGENTS.md&lt;/code&gt;, &lt;code&gt;hooks.json&lt;/code&gt;, &lt;code&gt;SKILL.md&lt;/code&gt;, and a PEP 723 &lt;code&gt;scripts/run_tool.py&lt;/code&gt; CLI script) in a single command:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# 1. Validate all 3 starter plugins in the cookbook repository&lt;/span&gt;
uv run examples/scaffold_custom_plugin.py

&lt;span class="c"&gt;# 2. Scaffold a brand-new custom plugin bundle from scratch&lt;/span&gt;
uv run examples/scaffold_custom_plugin.py &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--scaffold&lt;/span&gt; my-genomics-qc &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--skill&lt;/span&gt; vcf-filter-audit &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--description&lt;/span&gt; &lt;span class="s2"&gt;"Deterministic VCF quality filtering and AlphaGenome coordinate readiness checks."&lt;/span&gt;

&lt;span class="c"&gt;# 3. Install into your global Antigravity plugins directory&lt;/span&gt;
&lt;span class="nb"&gt;cp&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; plugins/bio-structural-qc ~/.gemini/config/plugins/bio-structural-qc
&lt;span class="nb"&gt;cp&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; plugins/genomics-variant-mcp ~/.gemini/config/plugins/genomics-variant-mcp
&lt;span class="nb"&gt;cp&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; plugins/epigraphy-citation-kit ~/.gemini/config/plugins/epigraphy-citation-kit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  6. Deep Dive: The 4 Public Antigravity MCP Server Patterns + 2 More Starter Plugins (&lt;code&gt;genomics-variant-mcp&lt;/code&gt; &amp;amp; &lt;code&gt;epigraphy-citation-kit&lt;/code&gt;)
&lt;/h2&gt;

&lt;p&gt;As documented in the public &lt;strong&gt;&lt;a href="https://antigravity.google/docs/mcp" rel="noopener noreferrer"&gt;Antigravity MCP Guide (&lt;code&gt;antigravity.google/docs/mcp&lt;/code&gt;)&lt;/a&gt;&lt;/strong&gt;, &lt;code&gt;mcp_config.json&lt;/code&gt; supports &lt;strong&gt;four core server connection patterns&lt;/strong&gt; across local developer tools and Google Cloud services:&lt;/p&gt;

&lt;h3&gt;
  
  
  A. The 4 Documented &lt;code&gt;mcp_config.json&lt;/code&gt; Patterns
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Pattern 1 - Local Stdio Subprocess (&lt;code&gt;command&lt;/code&gt; + &lt;code&gt;args&lt;/code&gt; + &lt;code&gt;env&lt;/code&gt;):&lt;/strong&gt;
Spawns a local MCP process over &lt;code&gt;stdio&lt;/code&gt; using &lt;code&gt;uv&lt;/code&gt;, &lt;code&gt;node&lt;/code&gt;, &lt;code&gt;python3&lt;/code&gt;, or &lt;code&gt;dart&lt;/code&gt; (for example, my cookbook's &lt;code&gt;genomics_variant_mcp&lt;/code&gt; server or local SQLite/file-system explorers).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pattern 2 - Google-Credentials Authenticated HTTP (&lt;code&gt;authProviderType: "google_credentials"&lt;/code&gt;):&lt;/strong&gt;
Connects directly to managed Google Cloud and developer MCP endpoints (such as &lt;strong&gt;BigQuery&lt;/strong&gt;, &lt;strong&gt;AlloyDB for PostgreSQL&lt;/strong&gt;, &lt;strong&gt;Spanner&lt;/strong&gt;, &lt;strong&gt;Cloud SQL&lt;/strong&gt;, &lt;strong&gt;Bigtable&lt;/strong&gt;, &lt;strong&gt;Dataplex&lt;/strong&gt;, and &lt;strong&gt;Google Developer Knowledge&lt;/strong&gt; at &lt;code&gt;https://developerknowledge.googleapis.com/mcp&lt;/code&gt;) using local Application Default Credentials (&lt;code&gt;gcloud auth application-default login&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pattern 3 - Remote Streamable HTTP with Custom Headers (&lt;code&gt;serverUrl&lt;/code&gt; + &lt;code&gt;headers&lt;/code&gt; + &lt;code&gt;timeoutSeconds&lt;/code&gt;):&lt;/strong&gt;
Connects to remote Streamable HTTP MCP endpoints (such as &lt;code&gt;https://gemini-api-docs-mcp.dev&lt;/code&gt; for &lt;code&gt;gemini_search_docs&lt;/code&gt; and &lt;code&gt;gemini_get_doc&lt;/code&gt;) with custom &lt;code&gt;Authorization&lt;/code&gt; headers and configurable timeouts (&lt;code&gt;timeoutSeconds: 600&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pattern 4 - OAuth 2.0 Remote Servers (Dynamic Client Registration or Manual &lt;code&gt;oauth&lt;/code&gt; Object):&lt;/strong&gt;
Authenticates against remote SaaS and enterprise MCP servers using automatic OAuth Dynamic Client Registration (DCR) or a manual &lt;code&gt;oauth&lt;/code&gt; (&lt;code&gt;clientId&lt;/code&gt;, &lt;code&gt;clientSecret&lt;/code&gt;) configuration redirecting to &lt;code&gt;https://antigravity.google/oauth-callback&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  B. Starter Plugin #2: &lt;code&gt;plugins/genomics-variant-mcp&lt;/code&gt; (Custom Python Stdio MCP Server + Specialist Subagent)
&lt;/h3&gt;

&lt;p&gt;To show how to package your own &lt;strong&gt;MCP server&lt;/strong&gt; and &lt;strong&gt;Specialist Subagent&lt;/strong&gt; inside an Antigravity plugin, the cookbook includes &lt;strong&gt;&lt;a href="https://github.com/RobinaMirbahar/antigravity-science-plugin-cookbook/tree/main/plugins/genomics-variant-mcp" rel="noopener noreferrer"&gt;&lt;code&gt;plugins/genomics-variant-mcp&lt;/code&gt;&lt;/a&gt;&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/RobinaMirbahar/antigravity-science-plugin-cookbook/blob/main/plugins/genomics-variant-mcp/mcp_config.json" rel="noopener noreferrer"&gt;&lt;code&gt;mcp_config.json&lt;/code&gt;&lt;/a&gt;&lt;/strong&gt; - Registers &lt;code&gt;genomics_variant_mcp&lt;/code&gt; via &lt;code&gt;uv run mcp/variant_mcp_server.py&lt;/code&gt; and marks both tools as &lt;code&gt;"eager": true&lt;/code&gt; so they load directly into the agent's native tool declarations:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&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;"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;"genomics_variant_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;"uv"&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="s2"&gt;"run"&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/variant_mcp_server.py"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"tools"&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;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"score_variant_impact"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"eager"&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="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"evaluate_lipinski_ro5"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"eager"&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="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;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/RobinaMirbahar/antigravity-science-plugin-cookbook/blob/main/plugins/genomics-variant-mcp/mcp/variant_mcp_server.py" rel="noopener noreferrer"&gt;&lt;code&gt;mcp/variant_mcp_server.py&lt;/code&gt;&lt;/a&gt;&lt;/strong&gt; - A zero-dependency PEP 723 JSON-RPC 2.0 Stdio MCP server implementing &lt;code&gt;initialize&lt;/code&gt;, &lt;code&gt;tools/list&lt;/code&gt;, and &lt;code&gt;tools/call&lt;/code&gt; for:

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;score_variant_impact&lt;/code&gt;: Scores 1-based &lt;code&gt;chr:pos:ref&amp;gt;alt&lt;/code&gt; SNVs (transition/transversion class, predicted AlphaGenome AVI impact score, PhyloP 100-way conservation, and molecular priority).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;evaluate_lipinski_ro5&lt;/code&gt;: Evaluates small-molecule leads against Lipinski's Rule of Five (&lt;code&gt;MW ≤ 500&lt;/code&gt;, &lt;code&gt;LogP ≤ 5&lt;/code&gt;, &lt;code&gt;HBD ≤ 5&lt;/code&gt;, &lt;code&gt;HBA ≤ 10&lt;/code&gt;) and Veber's polar surface area rule (&lt;code&gt;PSA ≤ 140 Å²&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/RobinaMirbahar/antigravity-science-plugin-cookbook/blob/main/plugins/genomics-variant-mcp/agents/clinical-variant-curator.md" rel="noopener noreferrer"&gt;&lt;code&gt;agents/clinical-variant-curator.md&lt;/code&gt;&lt;/a&gt;&lt;/strong&gt; - A specialist subagent (modeled on &lt;code&gt;firebase&lt;/code&gt;'s &lt;code&gt;agents/firestore-rules-author.md&lt;/code&gt;) with YAML frontmatter (&lt;code&gt;mainAgent: true&lt;/code&gt;, &lt;code&gt;subagent: true&lt;/code&gt;, &lt;code&gt;commandExecutionPolicy: auto&lt;/code&gt;) that enforces research-only molecular framing.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Run its built-in self-test with &lt;code&gt;uv&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;uv run plugins/genomics-variant-mcp/mcp/variant_mcp_server.py &lt;span class="nt"&gt;--self-test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  C. Starter Plugin #3: &lt;code&gt;plugins/epigraphy-citation-kit&lt;/code&gt; (Ancient Epigraphy Validator + &lt;code&gt;PreToolUse&lt;/code&gt; Hook)
&lt;/h3&gt;

&lt;p&gt;The third starter plugin, &lt;strong&gt;&lt;a href="https://github.com/RobinaMirbahar/antigravity-science-plugin-cookbook/tree/main/plugins/epigraphy-citation-kit" rel="noopener noreferrer"&gt;&lt;code&gt;plugins/epigraphy-citation-kit&lt;/code&gt;&lt;/a&gt;&lt;/strong&gt;, pairs a &lt;code&gt;PreToolUse&lt;/code&gt; lifecycle hook (&lt;code&gt;hooks.json&lt;/code&gt;) with a PEP 723 Leiden bracket normalizer (&lt;a href="https://github.com/RobinaMirbahar/antigravity-science-plugin-cookbook/blob/main/plugins/epigraphy-citation-kit/skills/epigraphy-gap-validator/scripts/validate_epigraphy.py" rel="noopener noreferrer"&gt;&lt;code&gt;validate_epigraphy.py&lt;/code&gt;&lt;/a&gt;) that automatically converts standard Leiden epigraphic brackets (&lt;code&gt;[---]&lt;/code&gt; and &lt;code&gt;[...]&lt;/code&gt;) into DeepMind Aeneas/Ithaca &lt;code&gt;#&lt;/code&gt; and &lt;code&gt;?&lt;/code&gt; tokens, checks for forbidden &lt;code&gt;##&lt;/code&gt; or &lt;code&gt;?#&lt;/code&gt; sequences, and pads short inscriptions to the 25-character minimum:&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 plugins/epigraphy-citation-kit/skills/epigraphy-gap-validator/scripts/validate_epigraphy.py &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--text&lt;/span&gt; &lt;span class="s2"&gt;"IMP CAESAR DIVI F [---] COS [...] III"&lt;/span&gt; &lt;span class="nt"&gt;--language&lt;/span&gt; latin
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  7. Bonus: Distilling Live Chat Sessions into Skills &amp;amp; Auditing Installed Bundles
&lt;/h2&gt;

&lt;h3&gt;
  
  
  A. Automatic Skill Distillation with &lt;code&gt;workflow-skill-creator&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Don't want to write &lt;code&gt;SKILL.md&lt;/code&gt; files from scratch? After completing any multi-step scientific workflow in chat, trigger the Science plugin's &lt;strong&gt;&lt;code&gt;workflow-skill-creator&lt;/code&gt;&lt;/strong&gt; skill:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"Package this workflow into a reusable skill."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It walks you through a mandatory &lt;strong&gt;4-round brainstorming protocol&lt;/strong&gt; (confirming inputs/outputs, error-handling rigidity, composing existing Science skills without duplicating code, and generating a CLI helper script) before writing the new skill to &lt;code&gt;~/.gemini/config/skills/&amp;lt;name&amp;gt;/&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  B. Managing Plugins with &lt;code&gt;/plugin&lt;/code&gt; &amp;amp; Auditing Installed Bundles (&lt;code&gt;inspect_installed_plugins.py&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;In Google Antigravity, you can install, enable, disable, or package plugins interactively using the built-in &lt;strong&gt;&lt;code&gt;/plugin&lt;/code&gt;&lt;/strong&gt; slash command or the &lt;strong&gt;Customizations -&amp;gt; Plugins&lt;/strong&gt; panel in the UI.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Directory-Keyed Discovery:&lt;/strong&gt; Antigravity resolves each installed bundle by its directory name under &lt;code&gt;~/.gemini/config/plugins/&amp;lt;dir&amp;gt;/&lt;/code&gt; (or workspace &lt;code&gt;.agents/plugins/&amp;lt;dir&amp;gt;/&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Zero-Context-Bloat Inventory:&lt;/strong&gt; Never dump raw &lt;code&gt;SKILL.md&lt;/code&gt; bodies across all installed plugins into your shell prompt. Instead, run &lt;a href="https://github.com/RobinaMirbahar/antigravity-science-plugin-cookbook/blob/main/examples/inspect_installed_plugins.py" rel="noopener noreferrer"&gt;&lt;code&gt;examples/inspect_installed_plugins.py&lt;/code&gt;&lt;/a&gt; to summarize manifest versions, skill counts, active &lt;code&gt;hooks.json&lt;/code&gt; files, &lt;code&gt;mcp_config.json&lt;/code&gt; servers, and &lt;code&gt;sidecar.json&lt;/code&gt; views:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Audit the 3 cookbook plugins in ./plugins&lt;/span&gt;
uv run examples/inspect_installed_plugins.py

&lt;span class="c"&gt;# Or audit your global Antigravity plugins directory&lt;/span&gt;
uv run examples/inspect_installed_plugins.py &lt;span class="nt"&gt;--root&lt;/span&gt; ~/.gemini/config/plugins
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  C. Installing &amp;amp; Inspecting Plugins from the Shell with &lt;code&gt;agy plugin&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;As documented in the &lt;strong&gt;&lt;a href="https://antigravity.google/docs/plugins" rel="noopener noreferrer"&gt;Antigravity Plugins Guide (&lt;code&gt;antigravity.google/docs/plugins&lt;/code&gt;)&lt;/a&gt;&lt;/strong&gt;, you can install the open-source DeepMind Science skills or my cookbook plugins directly via &lt;code&gt;npx&lt;/code&gt; or the &lt;code&gt;agy plugin&lt;/code&gt; CLI:&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 Google DeepMind's open-source science-skills bundle&lt;/span&gt;
npx skills add google-deepmind/science-skills/

&lt;span class="c"&gt;# Or install and inspect plugins using the Antigravity CLI&lt;/span&gt;
agy plugin &lt;span class="nb"&gt;install &lt;/span&gt;https://github.com/google-deepmind/science-skills
agy plugin list &lt;span class="nt"&gt;--json&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  8. Official Documentation &amp;amp; Scientific Database References
&lt;/h2&gt;

&lt;h3&gt;
  
  
  A. Official Google Antigravity Documentation
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://github.com/google-deepmind/science-skills" rel="noopener noreferrer"&gt;Google DeepMind Science Skills Open-Source Repository (&lt;code&gt;github.com/google-deepmind/science-skills&lt;/code&gt;)&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://antigravity.google/use-cases/science" rel="noopener noreferrer"&gt;Google Antigravity Science Use Cases &amp;amp; Demos (&lt;code&gt;antigravity.google/use-cases/science&lt;/code&gt;)&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://antigravity.google/docs" rel="noopener noreferrer"&gt;Google Antigravity Documentation Home (&lt;code&gt;antigravity.google/docs&lt;/code&gt;)&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://antigravity.google/docs/plugins" rel="noopener noreferrer"&gt;Plugins Guide (&lt;code&gt;antigravity.google/docs/plugins&lt;/code&gt;)&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://antigravity.google/docs/skills" rel="noopener noreferrer"&gt;Progressive-Disclosure Skills Guide (&lt;code&gt;antigravity.google/docs/skills&lt;/code&gt;)&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://antigravity.google/docs/rules" rel="noopener noreferrer"&gt;Rules Guide (&lt;code&gt;antigravity.google/docs/rules&lt;/code&gt;)&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://antigravity.google/docs/hooks" rel="noopener noreferrer"&gt;Lifecycle Hooks Guide (&lt;code&gt;antigravity.google/docs/hooks&lt;/code&gt;)&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://antigravity.google/docs/sidecars" rel="noopener noreferrer"&gt;Auxiliary Pane Sidecars Guide (&lt;code&gt;antigravity.google/docs/sidecars&lt;/code&gt;)&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://antigravity.google/docs/mcp" rel="noopener noreferrer"&gt;Model Context Protocol (MCP) Guide (&lt;code&gt;antigravity.google/docs/mcp&lt;/code&gt;)&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://antigravity.google/docs/permissions" rel="noopener noreferrer"&gt;Agent Permissions &amp;amp; Security (&lt;code&gt;antigravity.google/docs/permissions&lt;/code&gt;)&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://github.com/google-antigravity/antigravity-sdk-python" rel="noopener noreferrer"&gt;Google Antigravity Python SDK (&lt;code&gt;github.com/google-antigravity/antigravity-sdk-python&lt;/code&gt;)&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  B. Scientific AI Models, Databases &amp;amp; Open-Source Viewers
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://deepmind.google.com/science/alphagenome/" rel="noopener noreferrer"&gt;Google DeepMind AlphaGenome (&lt;code&gt;deepmind.google.com/science/alphagenome&lt;/code&gt;)&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://alphafold.ebi.ac.uk/" rel="noopener noreferrer"&gt;AlphaFold Protein Structure Database (&lt;code&gt;alphafold.ebi.ac.uk&lt;/code&gt;)&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://predictingthepast.com/" rel="noopener noreferrer"&gt;Google DeepMind Aeneas &amp;amp; Ithaca - Predicting the Past (&lt;code&gt;predictingthepast.com&lt;/code&gt;)&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://github.com/molstar/pdbe-molstar" rel="noopener noreferrer"&gt;PDBe Mol* 3D Biomolecular WebGL Viewer (&lt;code&gt;github.com/molstar/pdbe-molstar&lt;/code&gt;)&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://search.foldseek.com/search" rel="noopener noreferrer"&gt;Foldseek Structural Similarity Search (&lt;code&gt;search.foldseek.com&lt;/code&gt;)&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://www.ebi.ac.uk/chembl/" rel="noopener noreferrer"&gt;EMBL-EBI ChEMBL Bioactivity Database (&lt;code&gt;ebi.ac.uk/chembl&lt;/code&gt;)&lt;/a&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;a href="https://gnomad.broadinstitute.org/" rel="noopener noreferrer"&gt;gnomAD (&lt;code&gt;gnomad.broadinstitute.org&lt;/code&gt;)&lt;/a&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;a href="https://www.ncbi.nlm.nih.gov/clinvar/" rel="noopener noreferrer"&gt;NCBI ClinVar (&lt;code&gt;ncbi.nlm.nih.gov/clinvar&lt;/code&gt;)&lt;/a&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;a href="https://platform.opentargets.org/" rel="noopener noreferrer"&gt;Open Targets Platform (&lt;code&gt;platform.opentargets.org&lt;/code&gt;)&lt;/a&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;a href="https://open.fda.gov/apis/" rel="noopener noreferrer"&gt;openFDA API (&lt;code&gt;open.fda.gov/apis&lt;/code&gt;)&lt;/a&gt;&lt;/strong&gt;, and &lt;strong&gt;&lt;a href="https://clinicaltrials.gov/" rel="noopener noreferrer"&gt;ClinicalTrials.gov APIv2 (&lt;code&gt;clinicaltrials.gov&lt;/code&gt;)&lt;/a&gt;&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  C. Licensing, Academic Citations &amp;amp; Dataset Acknowledgements
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Google Antigravity Science Plugin License (&lt;code&gt;README.md&lt;/code&gt; &amp;amp; &lt;code&gt;SKILL_LICENSES.md&lt;/code&gt;):&lt;/strong&gt; Copyright 2026 Google LLC. All software and helper scripts in the Science Plugin (including &lt;code&gt;analyze_pae.py&lt;/code&gt;) are licensed under the &lt;strong&gt;&lt;a href="https://www.apache.org/licenses/LICENSE-2.0" rel="noopener noreferrer"&gt;Apache License, Version 2.0&lt;/a&gt;&lt;/strong&gt;, and all skill definitions and documentation materials (including &lt;code&gt;SKILL.md&lt;/code&gt; and &lt;code&gt;rules/AGENTS.md&lt;/code&gt;) are licensed under the &lt;strong&gt;&lt;a href="https://creativecommons.org/licenses/by/4.0/legalcode" rel="noopener noreferrer"&gt;Creative Commons Attribution 4.0 International License (CC-BY 4.0)&lt;/a&gt;&lt;/strong&gt;. Third-party biological and clinical databases referenced by individual skills are governed by their respective terms listed in &lt;code&gt;SKILL_LICENSES.md&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Google DeepMind &lt;code&gt;predictingthepast&lt;/code&gt; (&lt;code&gt;Aeneas&lt;/code&gt; &amp;amp; &lt;code&gt;Ithaca&lt;/code&gt;) Citations:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Aeneas (Latin):&lt;/strong&gt; Assael, Y., Sommerschield, T., Cooley, A. et al. &lt;em&gt;Contextualizing ancient texts with generative neural networks.&lt;/em&gt; &lt;strong&gt;Nature&lt;/strong&gt; 645, 141-147 (2025). (&lt;a href="https://github.com/google-deepmind/predictingthepast" rel="noopener noreferrer"&gt;github.com/google-deepmind/predictingthepast&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ithaca (Ancient Greek):&lt;/strong&gt; Assael, Y., Sommerschield, T., Shillingford, B. et al. &lt;em&gt;Restoring and attributing ancient texts using deep neural networks.&lt;/em&gt; &lt;strong&gt;Nature&lt;/strong&gt; 603, 280-283 (2022).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Epigraphic Dataset Acknowledgements (&lt;code&gt;predictingthepast&lt;/code&gt;):&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Ithaca (Ancient Greek):&lt;/strong&gt; Draws on the 2019 version of the &lt;em&gt;Searchable Greek Inscriptions&lt;/em&gt; database made available under Fair Use license by the &lt;strong&gt;Packard Humanities Institute&lt;/strong&gt;, generously supported by David Packard (&lt;a href="https://inscriptions.packhum.org" rel="noopener noreferrer"&gt;inscriptions.packhum.org&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Aeneas (Latin):&lt;/strong&gt; Trained on data from the &lt;strong&gt;Epigraphic Database Roma (EDR)&lt;/strong&gt; (&lt;a href="http://www.edr-edr.it/" rel="noopener noreferrer"&gt;edr-edr.it&lt;/a&gt;, CC-BY 4.0 on &lt;a href="https://zenodo.org/records/3575495" rel="noopener noreferrer"&gt;Zenodo&lt;/a&gt;), the &lt;strong&gt;Epigraphic Database Heidelberg (EDH)&lt;/strong&gt; (&lt;a href="https://edh.ub.uni-heidelberg.de/" rel="noopener noreferrer"&gt;edh.ub.uni-heidelberg.de&lt;/a&gt;, CC-BY-SA 4.0 on &lt;a href="https://zenodo.org/records/3575155" rel="noopener noreferrer"&gt;Zenodo&lt;/a&gt;), and the &lt;strong&gt;ETL repository for Epigraphic Database Clauss-Slaby (&lt;code&gt;EDCS_ETL&lt;/code&gt;)&lt;/strong&gt; (&lt;a href="http://www.manfredclauss.de/" rel="noopener noreferrer"&gt;manfredclauss.de&lt;/a&gt; and &lt;a href="https://github.com/sdam-au/EDCS_ETL" rel="noopener noreferrer"&gt;github.com/sdam-au/EDCS_ETL&lt;/a&gt;, CC-BY 4.0 on &lt;a href="https://zenodo.org/records/7072337" rel="noopener noreferrer"&gt;Zenodo&lt;/a&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Support, Star, Fork &amp;amp; Contribute on GitHub
&lt;/h2&gt;

&lt;p&gt;If you find the &lt;strong&gt;Antigravity Science Plugin Cookbook &amp;amp; Interactive 3D WebGL Studio&lt;/strong&gt; useful for your research or engineering workflows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Star this Repository:&lt;/strong&gt; &lt;a href="https://github.com/RobinaMirbahar/antigravity-science-plugin-cookbook" rel="noopener noreferrer"&gt;&lt;strong&gt;Star &lt;code&gt;RobinaMirbahar/antigravity-science-plugin-cookbook&lt;/code&gt; on GitHub&lt;/strong&gt;&lt;/a&gt; to bookmark the 3 starter plugins and help other developers discover the cookbook.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fork &amp;amp; Customize:&lt;/strong&gt; &lt;a href="https://github.com/RobinaMirbahar/antigravity-science-plugin-cookbook/fork" rel="noopener noreferrer"&gt;&lt;strong&gt;Fork &lt;code&gt;RobinaMirbahar/antigravity-science-plugin-cookbook&lt;/code&gt;&lt;/strong&gt;&lt;/a&gt; to scaffold and publish your own custom &lt;a href="https://antigravity.google/docs" rel="noopener noreferrer"&gt;&lt;strong&gt;Google Antigravity (&lt;code&gt;@google-antigravity&lt;/code&gt;)&lt;/strong&gt;&lt;/a&gt; plugins, progressive-disclosure skills, and MCP servers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Play Live in Your Browser:&lt;/strong&gt; &lt;a href="https://robinamirbahar.github.io/antigravity-science-plugin-cookbook/" rel="noopener noreferrer"&gt;&lt;strong&gt;Launch the Interactive 3D Biomolecular &amp;amp; Variant WebGL Studio&lt;/strong&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Official Ecosystem Links &amp;amp; Tags
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Google:&lt;/strong&gt; &lt;a href="https://github.com/google" rel="noopener noreferrer"&gt;github.com/google (&lt;code&gt;@google&lt;/code&gt;)&lt;/a&gt; | &lt;a href="https://about.google/" rel="noopener noreferrer"&gt;about.google&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Google Gemini API &amp;amp; SDKs:&lt;/strong&gt; &lt;a href="https://github.com/google-gemini" rel="noopener noreferrer"&gt;github.com/google-gemini (&lt;code&gt;@google-gemini&lt;/code&gt;)&lt;/a&gt; | &lt;a href="https://ai.google.dev/gemini-api/docs" rel="noopener noreferrer"&gt;ai.google.dev/gemini-api/docs&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Google DeepMind Science &amp;amp; Models:&lt;/strong&gt; &lt;a href="https://github.com/google-deepmind" rel="noopener noreferrer"&gt;github.com/google-deepmind (&lt;code&gt;@google-deepmind&lt;/code&gt;)&lt;/a&gt; | &lt;a href="https://deepmind.google/" rel="noopener noreferrer"&gt;deepmind.google&lt;/a&gt; | &lt;a href="https://deepmind.google.com/science/alphagenome/" rel="noopener noreferrer"&gt;AlphaGenome&lt;/a&gt; | &lt;a href="https://alphafold.ebi.ac.uk/" rel="noopener noreferrer"&gt;AlphaFold&lt;/a&gt; | &lt;a href="https://predictingthepast.com/" rel="noopener noreferrer"&gt;Aeneas &amp;amp; Ithaca&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Google Antigravity Platform:&lt;/strong&gt; &lt;a href="https://antigravity.google/docs" rel="noopener noreferrer"&gt;antigravity.google/docs&lt;/a&gt; | &lt;a href="https://antigravity.google/use-cases/science" rel="noopener noreferrer"&gt;antigravity.google/use-cases/science&lt;/a&gt; | &lt;a href="https://github.com/google-antigravity/antigravity-sdk-python" rel="noopener noreferrer"&gt;github.com/google-antigravity (&lt;code&gt;@google-antigravity&lt;/code&gt;)&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Google Cloud Platform:&lt;/strong&gt; &lt;a href="https://github.com/GoogleCloudPlatform" rel="noopener noreferrer"&gt;github.com/GoogleCloudPlatform (&lt;code&gt;@GoogleCloudPlatform&lt;/code&gt;)&lt;/a&gt; | &lt;a href="https://cloud.google.com/" rel="noopener noreferrer"&gt;cloud.google.com&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let me know in the comments what domain you're packaging into an Antigravity plugin next - whether it's &lt;strong&gt;3D structural biology&lt;/strong&gt;, &lt;strong&gt;genomic variant scoring&lt;/strong&gt;, &lt;strong&gt;ancient epigraphy&lt;/strong&gt;, or &lt;strong&gt;autonomous cloud SRE&lt;/strong&gt;!&lt;/p&gt;

</description>
      <category>ai</category>
      <category>gemini</category>
      <category>bioinformatics</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Comic Studio AI: Turning Voice &amp; Text Prompts into 4-Panel Comics with Google AI Studio, Gemini &amp; Imagen</title>
      <dc:creator>Robina Mirbahar</dc:creator>
      <pubDate>Fri, 23 Oct 2026 15:22:41 +0000</pubDate>
      <link>https://dev.to/gde/comic-studio-ai-turning-voice-text-prompts-into-4-panel-comics-with-google-ai-studio-gemini--2npc</link>
      <guid>https://dev.to/gde/comic-studio-ai-turning-voice-text-prompts-into-4-panel-comics-with-google-ai-studio-gemini--2npc</guid>
      <description>&lt;p&gt;&lt;em&gt;This post is my submission for &lt;a href="https://dev.to/deved/build-apps-with-google-ai-studio"&gt;DEV Education Track: Build Apps with Google AI Studio&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;As a &lt;strong&gt;Google Developer Expert (GDE) in AI &amp;amp; Cloud&lt;/strong&gt;, one of the biggest bottlenecks I see when teaching developers and students about multimodal AI architectures is turning abstract technical concepts into engaging, visual stories.&lt;/p&gt;

&lt;p&gt;For the &lt;strong&gt;Build Apps with Google AI Studio&lt;/strong&gt; Education Track, I built &lt;strong&gt;Comic Studio AI&lt;/strong&gt;, a full-stack multimodal web application generated with &lt;strong&gt;Google AI Studio's Build Mode&lt;/strong&gt;, powered by &lt;strong&gt;Google Gemini&lt;/strong&gt; (for structured 4-panel storyboard scripting, dialogue generation, and character consistency) and the &lt;strong&gt;Google Imagen API&lt;/strong&gt; (&lt;code&gt;@google/genai&lt;/code&gt; SDK) for rendering cohesive, high-contrast comic panels in under 60 seconds.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key Capabilities of Comic Studio AI
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;🎙️ &lt;strong&gt;Voice or Text Idea Input:&lt;/strong&gt; Speak or type a 1-sentence story idea or technical concept (for example, &lt;em&gt;"Explain how an AI Agent uses a RAG vector database and prompt guardrails"&lt;/em&gt;).&lt;/li&gt;
&lt;li&gt;🧠 &lt;strong&gt;Structured 4-Panel Storyboard Generation (Gemini):&lt;/strong&gt; Gemini acts as the narrative director, decomposing the raw idea into a strict JSON schema containing a shared &lt;code&gt;characterBible&lt;/code&gt; visual anchor and 4 sequential comic panels (&lt;code&gt;panelNumber&lt;/code&gt;, &lt;code&gt;captionBanner&lt;/code&gt;, &lt;code&gt;dialogue&lt;/code&gt;, and &lt;code&gt;imagenPrompt&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;⏸️ &lt;strong&gt;Optional Teacher Script-Review Gate (Human-in-the-Loop):&lt;/strong&gt; Before spending image generation quota, educators can review and edit the 4-panel &lt;code&gt;captionBanner&lt;/code&gt; and &lt;code&gt;dialogue&lt;/code&gt; text while it is still JSON, ensuring technical explanations (like RAG vector retrieval) are 100% accurate before a single pixel is rendered.&lt;/li&gt;
&lt;li&gt;🎨 &lt;strong&gt;Automated Multi-Panel Rendering (Imagen API):&lt;/strong&gt; Each approved panel prompt is prepended with the shared &lt;code&gt;characterBible&lt;/code&gt; anchor and passed to the &lt;strong&gt;Imagen API&lt;/strong&gt; (&lt;code&gt;imagen-4.0-generate-001&lt;/code&gt; / &lt;code&gt;imagen-3.0-generate-002&lt;/code&gt;) so character outfits, lighting, and color palettes remain consistent across all 4 panels.&lt;/li&gt;
&lt;li&gt;📄 &lt;strong&gt;Selective Single-Panel Re-Roll &amp;amp; Export:&lt;/strong&gt; Users can regenerate a single panel (&lt;code&gt;dirtyPanelNumbers: [2]&lt;/code&gt;) without re-rendering the entire strip, edit speech bubbles live, and export the finished 2x2 comic strip for technical blogs, classrooms, or documentation.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Prompt Used
&lt;/h2&gt;

&lt;p&gt;Here is the core structured system prompt I used inside &lt;strong&gt;Google AI Studio ("Build apps with Gemini")&lt;/strong&gt; to scaffold the React + TypeScript application and wire up both &lt;strong&gt;Gemini&lt;/strong&gt; and the &lt;strong&gt;Imagen API&lt;/strong&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Build a responsive React + TypeScript web application called &lt;strong&gt;Comic Studio AI&lt;/strong&gt; that turns a user's voice or text prompt into a 4-panel visual comic strip in under 60 seconds using Google Gemini and the Imagen API (&lt;code&gt;@google/genai&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Core Requirements:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Story &amp;amp; Prompt Input Bar:&lt;/strong&gt; Allow the user to enter a story topic or technical concept (via text input or browser Web Speech API voice capture), choose a visual art style (&lt;code&gt;Editorial Tech Comic&lt;/code&gt;, &lt;code&gt;Manga&lt;/code&gt;, &lt;code&gt;Kawaii Pastel&lt;/code&gt;, or &lt;code&gt;Superhero Ink&lt;/code&gt;), and toggle an optional &lt;code&gt;"Review Script Before Rendering"&lt;/code&gt; mode for educators.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gemini Storyboard Director (&lt;code&gt;responseSchema&lt;/code&gt;):&lt;/strong&gt; Call the Gemini API (&lt;code&gt;gemini-2.5-flash&lt;/code&gt;) with structured JSON output to generate a shared &lt;code&gt;characterBible&lt;/code&gt; string plus an array of exactly 4 panels. Each panel object must include:

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;panelNumber&lt;/code&gt; (1 to 4)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;captionBanner&lt;/code&gt; (short narrative header)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;dialogue&lt;/code&gt; (character speech bubble text, max 18 words)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;imagenPrompt&lt;/code&gt; (detailed visual prompt for the Imagen API that preserves character appearance and style consistency across all 4 panels).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Human-in-the-Loop Script Review &amp;amp; Imagen Panel Renderer:&lt;/strong&gt; Allow the user to inspect or edit the 4-panel script text, then call the &lt;strong&gt;Imagen API&lt;/strong&gt; (&lt;code&gt;imagen-4.0-generate-001&lt;/code&gt;) to render the 4 panel illustrations with skeleton loading states and single-panel regeneration (&lt;code&gt;dirtyPanelNumbers&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Interactive 2x2 Comic Grid &amp;amp; Export:&lt;/strong&gt; Render the 4 generated Imagen illustrations inside a crisp 2x2 comic book layout with bold ink borders, editable speech bubbles, and a "Download 4-Panel Comic" button.&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;h3&gt;
  
  
  🎥 Watch the 60-Second Live Walkthrough (YouTube)
&lt;/h3&gt;

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

&lt;h3&gt;
  
  
  🔗 Project Links &amp;amp; Source Code
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;💻 &lt;strong&gt;GitHub Repository:&lt;/strong&gt; &lt;a href="https://github.com/RobinaMirbahar/Comic-Studio-Ai" rel="noopener noreferrer"&gt;github.com/RobinaMirbahar/Comic-Studio-Ai&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🚀 &lt;strong&gt;Live Showcase &amp;amp; Architecture Overview:&lt;/strong&gt; &lt;a href="https://devpost.com/software/comiccrafter-ai" rel="noopener noreferrer"&gt;Comic Studio AI (Devpost &amp;amp; Cloud Run Demo)&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  🧩 Core Gemini + Imagen Integration Architecture
&lt;/h3&gt;

&lt;p&gt;Inside the generated Google AI Studio project, separating &lt;strong&gt;Stage 1: Narrative Scripting (Gemini)&lt;/strong&gt; from &lt;strong&gt;Stage 2: Visual Synthesis (Imagen)&lt;/strong&gt; using a strict &lt;code&gt;@google/genai&lt;/code&gt; TypeScript &lt;code&gt;Schema&lt;/code&gt; solves two real-world problems at once: it eliminates character drift across panels via a shared &lt;code&gt;characterBible&lt;/code&gt;, and it lets teachers pause to review or edit the 4-panel script before rendering images:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;GoogleGenAI&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Schema&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@google/genai&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Note: In Google AI Studio preview, GEMINI_API_KEY is injected into the sandbox environment.&lt;/span&gt;
&lt;span class="c1"&gt;// For production Cloud Run deployments, execute this module inside a server-side API route&lt;/span&gt;
&lt;span class="c1"&gt;// backed by server-side environment variables so the API key is never exposed to browser clients.&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ai&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;GoogleGenAI&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;apiKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;GEMINI_API_KEY&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;ComicPanel&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;panelNumber&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;captionBanner&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;dialogue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;imagenPrompt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;imageUrl&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;ComicStoryboard&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;characterBible&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;panels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ComicPanel&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;comicStoryboardSchema&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Schema&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Type&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;OBJECT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;A 4-panel comic storyboard with a shared character consistency bible.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;characterBible&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Type&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;STRING&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Exact visual description of the recurring character (clothing, glasses, colors) prepended to every panel prompt.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;panels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Type&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ARRAY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Exactly 4 sequential comic panels.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Type&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;OBJECT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;panelNumber&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Type&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;INTEGER&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
          &lt;span class="na"&gt;captionBanner&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Type&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;STRING&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
          &lt;span class="na"&gt;dialogue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Type&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;STRING&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
          &lt;span class="na"&gt;imagenPrompt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Type&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;STRING&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Scene action, camera angle, background setting, and lighting for this specific panel.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;panelNumber&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;captionBanner&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dialogue&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;imagenPrompt&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;characterBible&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;panels&lt;/span&gt;&lt;span class="dl"&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;// Stage 1: Draft the 4-panel text storyboard (allows optional human review before image rendering)&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;draftComicStoryboard&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;idea&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;artStyle&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ComicStoryboard&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;storyboardResponse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;ai&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;generateContent&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;gemini-2.5-flash&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;contents&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Create a 4-panel educational comic strip explaining: "&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;idea&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;". Visual style: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;artStyle&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;. Define a consistent characterBible and 4 sequential panels.`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;responseMimeType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;responseSchema&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;comicStoryboardSchema&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;temperature&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.4&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="na"&gt;parsed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ComicStoryboard&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;storyboardResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;{"characterBible":"","panels":[]}&lt;/span&gt;&lt;span class="dl"&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="na"&gt;characterBible&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;parsed&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;characterBible&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;panels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;parsed&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;panels&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;[]).&lt;/span&gt;&lt;span class="nf"&gt;slice&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="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Bound to max 4 panels&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Stage 2: Render all 4 panels (or selectively re-roll specific panel numbers) with Imagen&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;renderApprovedPanels&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;storyboard&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ComicStoryboard&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;artStyle&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;dirtyPanelNumbers&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ComicPanel&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;storyboard&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;panels&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&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="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;panel&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// If selective regeneration is requested, skip panels that are already approved&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dirtyPanelNumbers&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;dirtyPanelNumbers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;panel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;panelNumber&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;panel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;imageUrl&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;panel&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;

      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;imageResult&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;ai&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;generateImages&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;imagen-4.0-generate-001&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Or "imagen-3.0-generate-002"&lt;/span&gt;
        &lt;span class="na"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;storyboard&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;characterBible&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;. &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;panel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;imagenPrompt&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;, &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;artStyle&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; comic panel, bold ink outlines, vibrant colors`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;numberOfImages&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="na"&gt;aspectRatio&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;4:3&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;outputMimeType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;image/jpeg&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;

      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;base64Image&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;imageResult&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;generatedImages&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="nx"&gt;image&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;imageBytes&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="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;panel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;imageUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;base64Image&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="s2"&gt;`data:image/jpeg;base64,&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;base64Image&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;
      &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="p"&gt;})&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;h2&gt;
  
  
  My Experience
&lt;/h2&gt;

&lt;p&gt;Working through the &lt;strong&gt;Build Apps with Google AI Studio&lt;/strong&gt; Education Track highlighted three key engineering lessons that I now share in my workshops:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;From Idea to Full-Stack Multimodal Prototype in Minutes:&lt;/strong&gt; Google AI Studio's Build Mode handled all the React state management, responsive 2x2 comic grid layout, and &lt;code&gt;@google/genai&lt;/code&gt; SDK wiring from a single structured prompt, letting me focus immediately on prompt engineering and visual consistency rather than boilerplate setup.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Structured Outputs (&lt;code&gt;responseSchema&lt;/code&gt;) + a &lt;code&gt;characterBible&lt;/code&gt; Anchor Solve Character Drift:&lt;/strong&gt; When chaining text reasoning into image generation, asking Gemini to return a strict JSON schema with a top-level &lt;code&gt;characterBible&lt;/code&gt; field and prepending that descriptor to every &lt;code&gt;imagenPrompt&lt;/code&gt; eliminated the classic character drift problem across multi-panel comics.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Two-Stage Human-in-the-Loop Scripting Saves Quota and Improves Teaching Accuracy:&lt;/strong&gt; Splitting storyboard generation (&lt;code&gt;draftComicStoryboard&lt;/code&gt;) from image synthesis (&lt;code&gt;renderApprovedPanels&lt;/code&gt;) lets educators inspect and tweak the 4-panel explanation while it is still lightweight JSON text, and re-roll individual panels without burning quota on the entire strip.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  💬 Let's Connect!
&lt;/h3&gt;

&lt;p&gt;Have you tried chaining &lt;strong&gt;Gemini Structured Outputs&lt;/strong&gt; with the &lt;strong&gt;Imagen API&lt;/strong&gt; inside Google AI Studio yet? Drop what you're building in the comments below! 👇&lt;/p&gt;

</description>
      <category>deved</category>
      <category>learngoogleaistudio</category>
      <category>googleai</category>
      <category>gemini</category>
    </item>
    <item>
      <title>SlothSRE (NapOps): An Overnight Gemma 4 &amp; ADK Agent That Compresses 418 Lines of 3 AM Alerts into a 2-Line Morning Digest</title>
      <dc:creator>Robina Mirbahar</dc:creator>
      <pubDate>Wed, 21 Oct 2026 15:28:00 +0000</pubDate>
      <link>https://dev.to/gde/slothsre-napops-an-overnight-gemma-4-adk-agent-that-compresses-418-lines-of-3-am-alerts-into-a-1pk6</link>
      <guid>https://dev.to/gde/slothsre-napops-an-overnight-gemma-4-adk-agent-that-compresses-418-lines-of-3-am-alerts-into-a-1pk6</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/hacktoberfest-week3-2026-10-19"&gt;Hacktoberfest Open-Source AI Challenge Week 3: Slow and Steady&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;On-call software engineers lose sleep to noisy alert floods that repeat the same failure dozens of times before sunrise. When a Redis connection pool saturates during a batch job or an upstream webhook adds a new status string, alerting pipelines emit hundreds of lines of redundant stack traces across logs, CI runs, and chat channels. &lt;strong&gt;SlothSRE (NapOps)&lt;/strong&gt; is an open-source, local-first overnight triage agent built with open-weights &lt;strong&gt;Gemma 4&lt;/strong&gt;, &lt;strong&gt;Google Agent Development Kit (ADK)&lt;/strong&gt;, and &lt;strong&gt;Sentry Agent Tracing&lt;/strong&gt; so engineers can sleep through 3 AM alert storms and wake up to a two-line summary with a sandbox-tested git patch ready for one-click approval.&lt;/p&gt;

&lt;p&gt;Instead of paging a human for every retry loop, SlothSRE buffers non-critical overnight errors and runs a three-stage &lt;code&gt;SequentialAgent&lt;/code&gt; pipeline locally on &lt;code&gt;google/gemma-4-27b-it&lt;/code&gt; via Ollama or vLLM. In our benchmark run across 96 raw overnight alerts totaling 418 lines of stack traces and chat logs, SlothSRE collapsed the entire flood into 2 unique incident clusters (4 total summary lines), achieving a 99.04% reduction in morning reading volume and saving 42 minutes of manual log digging.&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%2Fcswag15wjdlq1vzdijbm.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fcswag15wjdlq1vzdijbm.jpg" alt="SlothSRE NapOps Architecture with Open-Weights Gemma 4, Google ADK, and Sentry Agent Tracing" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Overnight Metric&lt;/th&gt;
&lt;th&gt;Manual 3 AM Triage&lt;/th&gt;
&lt;th&gt;SlothSRE (NapOps) with Gemma 4&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Raw Overnight Events Ingested&lt;/td&gt;
&lt;td&gt;96 separate alerts&lt;/td&gt;
&lt;td&gt;2 deduplicated root-cause clusters&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Log &amp;amp; Stack-Trace Lines to Read&lt;/td&gt;
&lt;td&gt;418 raw lines&lt;/td&gt;
&lt;td&gt;4 summary lines (2 lines per cluster)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Log Noise Reduction&lt;/td&gt;
&lt;td&gt;0%&lt;/td&gt;
&lt;td&gt;99.04%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Patch Verification Before 8 AM&lt;/td&gt;
&lt;td&gt;None (manual reproduction)&lt;/td&gt;
&lt;td&gt;Automated local &lt;code&gt;pytest&lt;/code&gt; sandbox (312.4 ms &amp;amp; 184.6 ms)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Morning Triage Effort&lt;/td&gt;
&lt;td&gt;42 minutes of log correlation&lt;/td&gt;
&lt;td&gt;1-click patch apply &amp;amp; PR creation&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;You can run the complete SlothSRE benchmark and launch the interactive FastAPI Morning Dashboard in one command from the repository:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python scripts/run_slothsre_demo.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Running the demo executes the three-stage Gemma 4 + ADK overnight pipeline, records &lt;code&gt;gen_ai.agent&lt;/code&gt; and &lt;code&gt;gen_ai.tool&lt;/code&gt; spans via Sentry Agent Tracing, and verifies the live FastAPI dashboard endpoints (&lt;code&gt;GET /&lt;/code&gt; and &lt;code&gt;POST /api/approve/CLUSTER-01-REDIS-POOL&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;========================================================================================
🦥 SLOTHSRE (NAPOPS) - OVERNIGHT GEMMA 4 + ADK + SENTRY TRACING REPORT
========================================================================================
  Model                  : google/gemma-4-27b-it (local Ollama / vLLM)
  Raw 3 AM Events        : 96 alerts (418 raw log lines)
  Deduplicated Clusters  : 2 clusters (4 total summary lines)
  Log Noise Reduction    : 99.04%
  Morning Time Saved     : 42 minutes
  Sentry Root Trace ID   : 0772dffd4fbfd83d5e340590efbf735e
----------------------------------------------------------------------------------------
  [1] CLUSTER-01-REDIS-POOL (billing-worker) - Collapsed 62 alerts (310 lines)
      Line 1 (What Broke)  : At 03:10 UTC, billing-worker exhausted its 10-connection Redis pool during the nightly invoice batch, triggering 62 duplicate retry alerts.
      Line 2 (Verified Fix): Gemma 4 raised max_connections to 64 with 30s health checks in redis_client.py and passed all 18 local pytest assertions in 312.4 ms.
      1-Click Command      : git apply .slothsre/patches/CLUSTER-01-REDIS-POOL.patch &amp;amp;&amp;amp; gh pr create --fill
  [2] CLUSTER-02-PYDANTIC-V2-ENUM (webhook-ingest) - Collapsed 34 alerts (108 lines)
      Line 1 (What Broke)  : At 04:15 UTC, upstream payment webhooks began sending status='refund_queued', causing 34 Pydantic Literal validation rejections in webhook-ingest.
      Line 2 (Verified Fix): Gemma 4 added 'refund_queued' to WebhookEvent.status in models.py and verified schema round-trip compatibility in 184.6 ms.
      1-Click Command      : git apply .slothsre/patches/CLUSTER-02-PYDANTIC-V2-ENUM.patch &amp;amp;&amp;amp; gh pr create --fill
----------------------------------------------------------------------------------------
  [FastAPI UI Verified] GET / HTTP 200 (7491 bytes)
  [1-Click Approve API] POST /api/approve/CLUSTER-01-REDIS-POOL -&amp;gt; {'status': 'APPROVED_AND_APPLIED', 'cluster_id': 'CLUSTER-01-REDIS-POOL', 'service_name': 'billing-worker', 'executed_command': 'git apply .slothsre/patches/CLUSTER-01-REDIS-POOL.patch &amp;amp;&amp;amp; gh pr create --fill'}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To open the interactive browser dashboard on port 8095 and click the approval buttons directly (where &lt;code&gt;/api/approve/{cluster_id}&lt;/code&gt; validates &lt;code&gt;cluster_id&lt;/code&gt; against a strict &lt;code&gt;^CLUSTER-\d{2}-[A-Z0-9-]+$&lt;/code&gt; allowlist and verifies &lt;code&gt;patch.sandbox_pytest_passed == True&lt;/code&gt; before applying):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;uvicorn slothsre_napops.app:app &lt;span class="nt"&gt;--host&lt;/span&gt; 127.0.0.1 &lt;span class="nt"&gt;--port&lt;/span&gt; 8095
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Code
&lt;/h2&gt;

&lt;p&gt;The full open-source implementation is available on GitHub in the &lt;code&gt;slothsre_napops/&lt;/code&gt; package of &lt;a href="https://github.com/RobinaMirbahar/slothsre-napops" rel="noopener noreferrer"&gt;RobinaMirbahar/slothsre-napops&lt;/a&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;slothsre_napops/schemas.py&lt;/code&gt;: Strict Pydantic v2 contracts (&lt;code&gt;RawOvernightEvent&lt;/code&gt;, &lt;code&gt;VerifiedPatchArtifact&lt;/code&gt;, &lt;code&gt;TwoLineIncidentDigest&lt;/code&gt;, &lt;code&gt;SentryAgentSpanRecord&lt;/code&gt;, and &lt;code&gt;SlothMorningReport&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;slothsre_napops/agent.py&lt;/code&gt;: Three-stage Google ADK &lt;code&gt;SequentialAgent&lt;/code&gt; (&lt;code&gt;SlothSreOvernightPipeline&lt;/code&gt;) wired to local open-weights Gemma 4 via &lt;code&gt;LiteLlm&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;slothsre_napops/sentry_tracing.py&lt;/code&gt;: Sentry Agent Tracing instrumentation recording &lt;code&gt;gen_ai.agent&lt;/code&gt; and &lt;code&gt;gen_ai.tool&lt;/code&gt; spans with input/output token counts and step durations.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;slothsre_napops/app.py&lt;/code&gt;: FastAPI backend and Morning Coffee Digest web dashboard.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;scripts/run_slothsre_demo.py&lt;/code&gt;: Reproducible benchmark script that generates &lt;code&gt;articles/slothsre-napops/evidence/slothsre_benchmark.json&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How I Built It
&lt;/h2&gt;

&lt;p&gt;SlothSRE is structured around three open-source pillars: &lt;strong&gt;open-weights Gemma 4&lt;/strong&gt; for local reasoning, &lt;strong&gt;Google Agent Development Kit (ADK)&lt;/strong&gt; for deterministic multi-agent orchestration, and &lt;strong&gt;Sentry Agent Tracing (&lt;code&gt;sentry-sdk&lt;/code&gt;)&lt;/strong&gt; for observability across autonomous background steps.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Enforcing the Two-Line Morning Contract with Pydantic v2
&lt;/h3&gt;

&lt;p&gt;To make sure the agent never replaces a 418-line log flood with a 400-word essay or hallucinates a passing test run, &lt;code&gt;slothsre_napops/schemas.py&lt;/code&gt; enforces a strict schema where each incident cluster must resolve to &lt;code&gt;line_1_what_broke&lt;/code&gt;, &lt;code&gt;line_2_verified_fix&lt;/code&gt;, a &lt;code&gt;one_click_command&lt;/code&gt;, and a &lt;code&gt;VerifiedPatchArtifact&lt;/code&gt; cross-checked by &lt;code&gt;@model_validator(mode="after")&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;TwoLineIncidentDigest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BaseModel&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Strict 2-line morning summary enforcing the &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Slow and Steady&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt; anti-burnout contract.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

    &lt;span class="n"&gt;cluster_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Field&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;Deduplicated incident cluster ID.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;service_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Field&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;Impacted microservice.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;raw_events_collapsed&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="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&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;Number of duplicate raw overnight alerts merged into this digest.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;raw_lines_collapsed&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="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&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;Number of raw stack-trace lines compressed into 2 lines.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;line_1_what_broke&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&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;Line 1: Plain-English root cause in a single sentence.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;line_2_verified_fix&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&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;Line 2: Exact verified fix and test result in a single sentence.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;one_click_command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&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;Single CLI or git command to apply/merge the verified fix.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;patch&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;VerifiedPatchArtifact&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Field&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;Attached sandbox-verified patch.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="nd"&gt;@model_validator&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;after&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;enforce_verdict_alignment&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="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;TwoLineIncidentDigest&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;Prevents the LLM phrasing in Line 2 from contradicting the deterministic pytest verdict.&lt;/span&gt;&lt;span class="sh"&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;patch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sandbox_pytest_passed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;lowered&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;line_2_verified_fix&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;if&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;passed&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;lowered&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;verified&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;lowered&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;ValueError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;LLM phrasing claims verification passed, but sandbox_pytest_passed is False.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
                &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Orchestrating Gemma 4 Locally with Google ADK SequentialAgent
&lt;/h3&gt;

&lt;p&gt;In &lt;code&gt;slothsre_napops/agent.py&lt;/code&gt;, three specialized &lt;code&gt;LlmAgent&lt;/code&gt; stages share a local &lt;code&gt;ollama/gemma4:27b&lt;/code&gt; endpoint through &lt;code&gt;LiteLlm&lt;/code&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;NoiseFilterAgent&lt;/code&gt;&lt;/strong&gt;: Normalizes volatile memory addresses (&lt;code&gt;&amp;lt;HEX&amp;gt;&lt;/code&gt;), request UUIDs (&lt;code&gt;&amp;lt;UUID&amp;gt;&lt;/code&gt;), and ISO timestamps (&lt;code&gt;&amp;lt;TS&amp;gt;&lt;/code&gt;) before computing a SHA-256 stack fingerprint, collapsing 96 raw overnight events (62 Redis pool exhaustion errors totaling 310 lines and 34 Pydantic webhook errors totaling 108 lines) into 2 unique root-cause clusters.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;SandboxPatchAgent&lt;/code&gt;&lt;/strong&gt;: Generates a unified git diff for &lt;code&gt;services/billing_worker/redis_client.py&lt;/code&gt; and &lt;code&gt;services/webhook_ingest/models.py&lt;/code&gt;, then executes &lt;code&gt;pytest&lt;/code&gt; in a local sandbox (&lt;code&gt;312.4 ms&lt;/code&gt; and &lt;code&gt;184.6 ms&lt;/code&gt;) before marking the fix ready.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;TwoLineBriefAgent&lt;/code&gt;&lt;/strong&gt;: Formats the verified patches into the &lt;code&gt;SlothMorningReport&lt;/code&gt; output schema.
&lt;/li&gt;
&lt;/ol&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;build_slothsre_adk_pipeline&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Optional&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="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;SequentialAgent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Builds the 3-stage Google ADK SequentialAgent powered by open-weights Gemma 4.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;gemma_model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;_build_local_gemma4_model&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;noise_filter_agent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;LlmAgent&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;NoiseFilterAgent&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="n"&gt;gemma_model&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;Deduplicates hundreds of 3 AM stack traces, CI failures, and chat messages into unique root causes.&lt;/span&gt;&lt;span class="sh"&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="p"&gt;(&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;You are the SlothSRE NoiseFilterAgent running open-weights Gemma 4 locally while the human sleeps. &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Group duplicate stack traces and flaky retries using `deduplicate_overnight_alerts`.&lt;/span&gt;&lt;span class="sh"&gt;"&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;deduplicate_overnight_alerts&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="n"&gt;output_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;deduplicated_clusters&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;sandbox_patch_agent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;LlmAgent&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;SandboxPatchAgent&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="n"&gt;gemma_model&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;Drafts minimal git diffs for each overnight cluster and runs local pytest verification.&lt;/span&gt;&lt;span class="sh"&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="p"&gt;(&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;For each unique incident cluster in {deduplicated_clusters}, generate a minimal patch &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;and verify it with `verify_patch_in_local_sandbox`.&lt;/span&gt;&lt;span class="sh"&gt;"&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;verify_patch_in_local_sandbox&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="n"&gt;output_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;verified_patches&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;two_line_brief_agent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;LlmAgent&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;TwoLineBriefAgent&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="n"&gt;gemma_model&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;Distills verified overnight patches into a strict 2-line Morning Coffee Digest.&lt;/span&gt;&lt;span class="sh"&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="p"&gt;(&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Compress {verified_patches} into a SlothMorningReport where every incident has &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;exactly 2 sentences (Line 1: What broke; Line 2: Verified fix) plus a 1-click command.&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;SlothMorningReport&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;output_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;morning_report&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="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;SequentialAgent&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;SlothSreOvernightPipeline&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;Sequential ADK pipeline that triages overnight alerts locally with Gemma 4.&lt;/span&gt;&lt;span class="sh"&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;noise_filter_agent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sandbox_patch_agent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;two_line_brief_agent&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;
  
  
  3. Instrumenting Overnight Agent Runs with Sentry Agent Tracing
&lt;/h3&gt;

&lt;p&gt;When an autonomous agent runs while you are asleep, you need verifiable proof of which tools it called, how many tokens it consumed, and how long each step took. In &lt;code&gt;slothsre_napops/sentry_tracing.py&lt;/code&gt;, &lt;code&gt;SlothSentryTracer&lt;/code&gt; wraps each ADK agent and tool invocation in a Sentry span with &lt;code&gt;gen_ai.system&lt;/code&gt;, &lt;code&gt;gen_ai.request.model&lt;/code&gt;, &lt;code&gt;gen_ai.usage.input_tokens&lt;/code&gt;, and &lt;code&gt;gen_ai.usage.output_tokens&lt;/code&gt;:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Span ID&lt;/th&gt;
&lt;th&gt;Sentry Op&lt;/th&gt;
&lt;th&gt;Agent / Tool Step&lt;/th&gt;
&lt;th&gt;Input / Output Tokens&lt;/th&gt;
&lt;th&gt;Duration (ms)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;de8105cb2e489d3e&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;gen_ai.agent&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;NoiseFilterAgent.deduplicate_overnight_alerts&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;3840 / 192&lt;/td&gt;
&lt;td&gt;412.6 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;482510772a320ab9&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;gen_ai.tool&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;SandboxPatchAgent.verify_patch_in_local_sandbox[CLUSTER-01-REDIS-POOL]&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;620 / 148&lt;/td&gt;
&lt;td&gt;312.4 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ca536bd9739c2577&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;gen_ai.tool&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;SandboxPatchAgent.verify_patch_in_local_sandbox[CLUSTER-02-PYDANTIC-V2-ENUM]&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;540 / 116&lt;/td&gt;
&lt;td&gt;184.6 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;a2b713fa35fa6773&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;gen_ai.agent&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;TwoLineBriefAgent.synthesize_morning_report&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;890 / 210&lt;/td&gt;
&lt;td&gt;268.4 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Why Does Open Innovation Matter?
&lt;/h2&gt;

&lt;p&gt;Production stack traces, local repository paths, database connection strings, and on-call chat transcripts contain sensitive infrastructure metadata that many teams cannot upload to third-party metered cloud LLM endpoints. Building SlothSRE on &lt;strong&gt;open-weights Gemma 4&lt;/strong&gt; and the open-source &lt;strong&gt;Google Agent Development Kit (ADK)&lt;/strong&gt; unlocks three critical advantages that closed APIs cannot match:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Local Execution for Raw Logs and Code:&lt;/strong&gt; Running &lt;code&gt;google/gemma-4-27b-it&lt;/code&gt; locally via Ollama or on a private VPC-isolated Cloud Run GPU keeps every stack trace, environment variable name, and git diff inside your own machine or private network perimeter.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Zero Per-Token Anxiety During Alert Storms:&lt;/strong&gt; A runaway retry loop at 3 AM can generate thousands of log lines in minutes. Piping an unbounded log storm into a metered commercial API risks a surprise bill before breakfast; running open-weights Gemma 4 locally incurs zero per-token API fees no matter how noisy the alert storm gets.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Offline &amp;amp; Local-Sandbox Determinism:&lt;/strong&gt; Because both the model weights and the ADK &lt;code&gt;SequentialAgent&lt;/code&gt; pipeline run locally alongside &lt;code&gt;pytest&lt;/code&gt;, SlothSRE can test candidate patches against the local codebase without requiring external network access.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The Lazy Payoff
&lt;/h2&gt;

&lt;p&gt;Before SlothSRE, reviewing an overnight batch failure meant opening four browser tabs (Cloud Run logs, GitHub Actions, Slack &lt;code&gt;#oncall-sre&lt;/code&gt;, and local IDE search), scrolling through 418 lines of repeated tracebacks across 96 alerts, reproducing the failure locally, and writing a PR description from scratch.&lt;/p&gt;

&lt;p&gt;With SlothSRE running on open-weights Gemma 4, those 96 noisy alerts are already collapsed into 2 two-line cards with passing &lt;code&gt;pytest&lt;/code&gt; checks (&lt;code&gt;312.4 ms&lt;/code&gt; and &lt;code&gt;184.6 ms&lt;/code&gt;) before 8:00 AM. That saves 42 minutes of manual morning triage per incident storm and lets the on-call engineer review, approve, and open both pull requests in under 30 seconds.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prize Categories
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Best Use of Gemma&lt;/strong&gt;: Uses open-weights &lt;strong&gt;Gemma 4 (&lt;code&gt;google/gemma-4-27b-it&lt;/code&gt;)&lt;/strong&gt; via local Ollama / vLLM as the reasoning engine across all three Google ADK sub-agents (&lt;code&gt;NoiseFilterAgent&lt;/code&gt;, &lt;code&gt;SandboxPatchAgent&lt;/code&gt;, and &lt;code&gt;TwoLineBriefAgent&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Best Use of Sentry Agent Tracing&lt;/strong&gt;: Instruments every overnight agent step and sandbox tool call with &lt;code&gt;sentry-sdk&lt;/code&gt; &lt;code&gt;gen_ai.agent&lt;/code&gt; and &lt;code&gt;gen_ai.tool&lt;/code&gt; spans (&lt;code&gt;gen_ai.system&lt;/code&gt;, &lt;code&gt;gen_ai.request.model&lt;/code&gt;, &lt;code&gt;gen_ai.usage.input_tokens&lt;/code&gt;, &lt;code&gt;gen_ai.usage.output_tokens&lt;/code&gt;) and surfaces the trace table directly in the morning dashboard.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Official Documentation &amp;amp; Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;SlothSRE (NapOps) Open-Source Repository on GitHub:&lt;/strong&gt; &lt;a href="https://github.com/RobinaMirbahar/slothsre-napops" rel="noopener noreferrer"&gt;https://github.com/RobinaMirbahar/slothsre-napops&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SlothSRE (NapOps) Core Package (&lt;code&gt;slothsre_napops/&lt;/code&gt;):&lt;/strong&gt; &lt;a href="https://github.com/RobinaMirbahar/slothsre-napops/tree/main/slothsre_napops" rel="noopener noreferrer"&gt;https://github.com/RobinaMirbahar/slothsre-napops/tree/main/slothsre_napops&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reproducible Benchmark Script (&lt;code&gt;run_slothsre_demo.py&lt;/code&gt;):&lt;/strong&gt; &lt;a href="https://github.com/RobinaMirbahar/slothsre-napops/blob/main/scripts/run_slothsre_demo.py" rel="noopener noreferrer"&gt;https://github.com/RobinaMirbahar/slothsre-napops/blob/main/scripts/run_slothsre_demo.py&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hacktoberfest Open-Source AI Challenge Week 3 (Slow and Steady):&lt;/strong&gt; &lt;a href="https://dev.to/challenges/hacktoberfest-week3-2026-10-19"&gt;https://dev.to/challenges/hacktoberfest-week3-2026-10-19&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;HF26 Challenge Hub (Best Use of Gemma &amp;amp; Sentry Categories):&lt;/strong&gt; &lt;a href="https://dev.to/challenges/hf26"&gt;https://dev.to/challenges/hf26&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Google Gemma Open-Weights Models:&lt;/strong&gt; &lt;a href="https://cloud.google.com/vertex-ai/generative-ai/docs/open-models/use-gemma" rel="noopener noreferrer"&gt;https://cloud.google.com/vertex-ai/generative-ai/docs/open-models/use-gemma&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Google Agent Development Kit (ADK) Documentation:&lt;/strong&gt; &lt;a href="https://google.github.io/adk-docs/" rel="noopener noreferrer"&gt;https://google.github.io/adk-docs/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sentry AI Agent Monitoring &amp;amp; Tracing Documentation:&lt;/strong&gt; &lt;a href="https://docs.sentry.io/product/ai-monitoring/" rel="noopener noreferrer"&gt;https://docs.sentry.io/product/ai-monitoring/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ollama Local Model Runner:&lt;/strong&gt; &lt;a href="https://ollama.com/" rel="noopener noreferrer"&gt;https://ollama.com/&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>devchallenge</category>
      <category>hf26challenge</category>
      <category>gemma</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Event-Driven Multi-Agent Pipelines on Google Cloud with ADK, Gemma 3 and Eventarc</title>
      <dc:creator>Robina Mirbahar</dc:creator>
      <pubDate>Tue, 20 Oct 2026 03:50:56 +0000</pubDate>
      <link>https://dev.to/gde/beyond-chatbots-and-cron-jobs-event-driven-multi-agent-pipelines-on-google-cloud-with-adk-gemma-3-3cbk</link>
      <guid>https://dev.to/gde/beyond-chatbots-and-cron-jobs-event-driven-multi-agent-pipelines-on-google-cloud-with-adk-gemma-3-3cbk</guid>
      <description>&lt;p&gt;&lt;em&gt;This post is my submission for &lt;a href="https://dev.to/deved/build-multi-agent-systems"&gt;DEV Education Track: Build Multi-Agent Systems with ADK&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This article provides a step by step architectural and deployment guide for &lt;strong&gt;StreamForge&lt;/strong&gt;, a real-time event-driven multi-agent pipeline built with the &lt;a href="https://google.github.io/adk-docs/" rel="noopener noreferrer"&gt;Google Agent Development Kit (ADK)&lt;/a&gt;, &lt;a href="https://cloud.google.com/vertex-ai/generative-ai/docs/open-models/use-gemma" rel="noopener noreferrer"&gt;open-weights Gemma 3 (&lt;code&gt;gemma3:12b&lt;/code&gt;)&lt;/a&gt;, &lt;a href="https://cloud.google.com/eventarc/docs" rel="noopener noreferrer"&gt;Google Cloud Eventarc&lt;/a&gt;, &lt;a href="https://cloud.google.com/pubsub/docs" rel="noopener noreferrer"&gt;Cloud Pub/Sub&lt;/a&gt;, and &lt;a href="https://cloud.google.com/run/docs" rel="noopener noreferrer"&gt;Google Cloud Run&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Repository: &lt;a href="https://github.com/RobinaMirbahar/streamforge-event-adk" rel="noopener noreferrer"&gt;github.com/RobinaMirbahar/streamforge-event-adk&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Enterprise data platforms operate on real-time state changes: a product engineering team uploads a release specification (&lt;code&gt;vertex-vector-sync-v4.2.json&lt;/code&gt;) to a &lt;a href="https://cloud.google.com/storage/docs" rel="noopener noreferrer"&gt;Google Cloud Storage&lt;/a&gt; bucket, a streaming job commits a partition to &lt;a href="https://cloud.google.com/bigquery/docs" rel="noopener noreferrer"&gt;BigQuery&lt;/a&gt;, or a partner service publishes a schema event to &lt;a href="https://cloud.google.com/pubsub/docs" rel="noopener noreferrer"&gt;Cloud Pub/Sub&lt;/a&gt;. Connecting &lt;a href="https://cloud.google.com/eventarc/docs" rel="noopener noreferrer"&gt;Google Cloud Eventarc&lt;/a&gt; directly to a multi-agent &lt;a href="https://google.github.io/adk-docs/agents/workflow-agents/" rel="noopener noreferrer"&gt;Google ADK workflow runtime&lt;/a&gt; on &lt;a href="https://cloud.google.com/run/docs" rel="noopener noreferrer"&gt;Cloud Run&lt;/a&gt; triggers autonomous workflows within &lt;code&gt;200 ms&lt;/code&gt; of an object landing in storage while scaling to &lt;code&gt;0&lt;/code&gt; instances when the bucket is idle.&lt;/p&gt;




&lt;h4&gt;
  
  
  Why Combine Eventarc with ADK &lt;code&gt;ParallelAgent&lt;/code&gt; and &lt;code&gt;LoopAgent&lt;/code&gt;?
&lt;/h4&gt;

&lt;p&gt;Processing a multi-regional product release requires three distinct tasks: extracting technical benchmarks from the raw JSON payload, translating launch messaging across target locales (&lt;code&gt;en_US&lt;/code&gt;, &lt;code&gt;de_DE&lt;/code&gt;, &lt;code&gt;ja_JP&lt;/code&gt;), and simulating 12-month Annual Recurring Revenue (ARR) expansion under regional B2B currency rules. Running those three steps sequentially increases end-to-end latency, while running them in parallel without a verification step risks publishing unrounded foreign-exchange prices.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Architecture Pattern&lt;/th&gt;
&lt;th&gt;Trigger Mechanism&lt;/th&gt;
&lt;th&gt;Execution Topology&lt;/th&gt;
&lt;th&gt;Cross-Agent Consistency Check&lt;/th&gt;
&lt;th&gt;Duplicate Event Protection&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;🥇 &lt;strong&gt;Eventarc + ADK ParallelAgent &amp;amp; LoopAgent&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;Real-time &lt;strong&gt;CloudEvents v1.0&lt;/strong&gt; (&lt;code&gt;&amp;lt; 200 ms&lt;/code&gt; lag)&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;3 concurrent branches&lt;/strong&gt; (&lt;code&gt;3x&lt;/code&gt; fan-out) + &lt;strong&gt;LoopAgent critic&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;Iterative audit repairs EUR/JPY pricing until &lt;code&gt;quality_score == 1.0&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Firestore &lt;code&gt;ce-id&lt;/code&gt; ledger short-circuits replays in &lt;code&gt;&amp;lt; 5 ms&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🥈 &lt;strong&gt;Scheduled ADK SequentialAgent&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;Fixed cron schedule&lt;/td&gt;
&lt;td&gt;Linear 3-stage chain&lt;/td&gt;
&lt;td&gt;Single-pass sequential handoff&lt;/td&gt;
&lt;td&gt;Date-keyed Firestore lock&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🥉 &lt;strong&gt;Single Monolithic Prompt&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;Manual human chat prompt&lt;/td&gt;
&lt;td&gt;Single LLM call&lt;/td&gt;
&lt;td&gt;Unchecked single-pass output&lt;/td&gt;
&lt;td&gt;Manual retry handling&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h4&gt;
  
  
  End-to-End Event-Driven Architecture on Google Cloud
&lt;/h4&gt;

&lt;p&gt;&lt;a 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%2F837sdaj8gqhcejy2m8dv.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F837sdaj8gqhcejy2m8dv.jpg" alt="Figure 1: Real-Time Event-Driven Agent Architecture on Google Cloud" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Tier 1: Event Ingestion and Routing:&lt;/strong&gt; Uploading &lt;code&gt;releases/2026-10/vertex-vector-sync-v4.2.json&lt;/code&gt; to &lt;code&gt;gs://streamforge-launch-inbox&lt;/code&gt; emits a native &lt;code&gt;google.cloud.storage.object.v1.finalized&lt;/code&gt; event. &lt;strong&gt;Google Cloud Eventarc&lt;/strong&gt; wraps the notification in a CNCF &lt;strong&gt;CloudEvents v1.0&lt;/strong&gt; envelope (&lt;code&gt;ce-id&lt;/code&gt;, &lt;code&gt;ce-type&lt;/code&gt;, &lt;code&gt;ce-source&lt;/code&gt;, &lt;code&gt;ce-time&lt;/code&gt;) and delivers it over an OIDC-authenticated &lt;strong&gt;Cloud Pub/Sub&lt;/strong&gt; push subscription.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tier 2: Serverless Multi-Agent Runtime (Cloud Run):&lt;/strong&gt; A private &lt;strong&gt;FastAPI&lt;/strong&gt; receiver checks the incoming &lt;code&gt;ce-id&lt;/code&gt; header (&lt;code&gt;ce-98104271-gcs-finalized&lt;/code&gt;) against &lt;strong&gt;Cloud Firestore&lt;/strong&gt;. New events execute the &lt;strong&gt;Google ADK&lt;/strong&gt; workflow (&lt;code&gt;ParallelAgent&lt;/code&gt; → &lt;code&gt;LoopAgent&lt;/code&gt; → &lt;code&gt;LlmAgent&lt;/code&gt;) powered by &lt;strong&gt;Gemma 3 12B&lt;/strong&gt; via &lt;code&gt;LiteLlm&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tier 3: State and Downstream Sink:&lt;/strong&gt; The final publisher agent validates the output against the Pydantic &lt;code&gt;EventDrivenLaunchManifest&lt;/code&gt; schema and commits both the manifest (&lt;code&gt;MANIFEST-SF-VECTOR-SYNC-4.2&lt;/code&gt;) and the &lt;code&gt;ce-id&lt;/code&gt; deduplication record to &lt;strong&gt;Cloud Firestore&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;




&lt;h4&gt;
  
  
  Orchestrating &lt;code&gt;ParallelAgent&lt;/code&gt; Fan-Out and &lt;code&gt;LoopAgent&lt;/code&gt; Self-Correction
&lt;/h4&gt;

&lt;p&gt;&lt;a 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%2Fwy6xfcu92oaoddqxzrqf.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwy6xfcu92oaoddqxzrqf.jpg" alt="Figure 2: Orchestrating ADK ParallelAgent Fan-Out and LoopAgent Self-Correction" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In &lt;strong&gt;Google ADK&lt;/strong&gt;, all branches inside a &lt;code&gt;ParallelAgent&lt;/code&gt; share the same &lt;code&gt;InvocationContext.session.state&lt;/code&gt;. Assigning a distinct &lt;code&gt;output_key&lt;/code&gt; to each branch isolates their writes cleanly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;TechnicalSpecExtractorAgent&lt;/code&gt; writes engineering benchmarks to &lt;code&gt;output_key="extracted_specs"&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;GlobalLocalizationAgent&lt;/code&gt; writes localized headlines and draft currency tiers to &lt;code&gt;output_key="localized_copy"&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;RevenuePricingSimulatorAgent&lt;/code&gt; writes the 12-month ARR forecast and regional FX compliance rules to &lt;code&gt;output_key="pricing_simulation"&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once all &lt;code&gt;3&lt;/code&gt; parallel branches complete, &lt;code&gt;QualityCritiqueRefinementLoop&lt;/code&gt; (&lt;code&gt;LoopAgent&lt;/code&gt; with &lt;code&gt;max_iterations=3&lt;/code&gt;) invokes &lt;code&gt;LaunchReadinessCriticAgent&lt;/code&gt; to audit the combined state. When &lt;code&gt;GlobalLocalizationAgent&lt;/code&gt; converts the &lt;code&gt;$499/mo&lt;/code&gt; Growth Tier at the raw &lt;code&gt;0.92&lt;/code&gt; EUR exchange rate (&lt;code&gt;€459.08/mo&lt;/code&gt;), Iteration &lt;code&gt;1&lt;/code&gt; of the &lt;code&gt;LoopAgent&lt;/code&gt; flags the violation against the &lt;code&gt;de_DE&lt;/code&gt; rule requiring VAT-exclusive B2B prices rounded to the nearest &lt;code&gt;€5&lt;/code&gt; (&lt;code&gt;quality_score = 0.72&lt;/code&gt;) and updates the pricing tier to &lt;code&gt;€460/mo&lt;/code&gt;. On Iteration &lt;code&gt;2&lt;/code&gt;, the audit reaches &lt;code&gt;quality_score = 1.0&lt;/code&gt; and invokes &lt;code&gt;exit_quality_loop()&lt;/code&gt;, setting &lt;code&gt;tool_context.actions.escalate = True&lt;/code&gt; to exit the loop immediately.&lt;/p&gt;




&lt;h4&gt;
  
  
  At This Point You Should Have
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Python &lt;code&gt;3.10+&lt;/code&gt; (&lt;code&gt;3.11&lt;/code&gt; recommended) with &lt;code&gt;google-adk&amp;gt;=1.0.0&lt;/code&gt;, &lt;code&gt;litellm&lt;/code&gt;, &lt;code&gt;fastapi&lt;/code&gt;, and &lt;code&gt;pydantic&lt;/code&gt; installed.&lt;/li&gt;
&lt;li&gt;A Google Cloud project with &lt;code&gt;Cloud Run&lt;/code&gt;, &lt;code&gt;Eventarc&lt;/code&gt;, &lt;code&gt;Cloud Pub/Sub&lt;/code&gt;, &lt;code&gt;Cloud Storage&lt;/code&gt;, and &lt;code&gt;Cloud Firestore&lt;/code&gt; APIs enabled.&lt;/li&gt;
&lt;li&gt;Access to &lt;strong&gt;Gemma 3 12B&lt;/strong&gt; (&lt;code&gt;ollama_chat/gemma3:12b&lt;/code&gt; locally via Ollama or &lt;code&gt;google/gemma-3-12b-it&lt;/code&gt; on a Cloud Run &lt;code&gt;NVIDIA L4&lt;/code&gt; &lt;code&gt;24 GB&lt;/code&gt; GPU service).&lt;/li&gt;
&lt;/ul&gt;




&lt;h4&gt;
  
  
  Step 1: Define the CloudEvent and Launch Manifest Schemas
&lt;/h4&gt;

&lt;p&gt;The pipeline enforces typed contracts at both boundaries: &lt;code&gt;CloudEventEnvelope&lt;/code&gt; validates the incoming Eventarc HTTP headers and payload, while &lt;code&gt;EventDrivenLaunchManifest&lt;/code&gt; constrains the final &lt;code&gt;ReleasePublisherAgent&lt;/code&gt; output in &lt;code&gt;streamforge_agent/schemas.py&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;==&amp;gt; [1/6] Enabling Cloud Run, Eventarc, Pub/Sub, Storage, and Firestore APIs...
==&amp;gt; [2/6] Creating Cloud Storage Inbox Bucket &amp;amp; Dead-Letter Pub/Sub Topic...
==&amp;gt; [3/6] Creating Least-Privilege Service Accounts...
==&amp;gt; [4/6] Deploying StreamForge ADK Service to Cloud Run (private ingress)...
Service [streamforge-event-adk] revision [streamforge-event-adk-00001-x8k] has been deployed and is serving 100 percent of traffic.
==&amp;gt; [5/6] Granting Cloud Run Invoker + Eventarc EventReceiver to Eventarc SA...
==&amp;gt; [6/6] Creating Eventarc Trigger for google.cloud.storage.object.v1.finalized...
Created trigger [streamforge-gcs-release-trigger] in [us-central1].
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h4&gt;
  
  
  Step 2: Implement the Parallel Enrichment and Loop Escalation Tools
&lt;/h4&gt;

&lt;p&gt;In &lt;code&gt;streamforge_agent/tools.py&lt;/code&gt;, each specialist tool exposes typed parameters and docstrings for &lt;strong&gt;Gemma 3&lt;/strong&gt; function calling, while &lt;code&gt;exit_quality_loop&lt;/code&gt; sets &lt;code&gt;tool_context.actions.escalate = True&lt;/code&gt; on the injected ADK &lt;code&gt;ToolContext&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;==&amp;gt; [1/6] Enabling Cloud Run, Eventarc, Pub/Sub, Storage, and Firestore APIs...
==&amp;gt; [2/6] Creating Cloud Storage Inbox Bucket &amp;amp; Dead-Letter Pub/Sub Topic...
==&amp;gt; [3/6] Creating Least-Privilege Service Accounts...
==&amp;gt; [4/6] Deploying StreamForge ADK Service to Cloud Run (private ingress)...
Service [streamforge-event-adk] revision [streamforge-event-adk-00001-x8k] has been deployed and is serving 100 percent of traffic.
==&amp;gt; [5/6] Granting Cloud Run Invoker + Eventarc EventReceiver to Eventarc SA...
==&amp;gt; [6/6] Creating Eventarc Trigger for google.cloud.storage.object.v1.finalized...
Created trigger [streamforge-gcs-release-trigger] in [us-central1].
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h4&gt;
  
  
  Step 3: Wire &lt;code&gt;ParallelAgent&lt;/code&gt;, &lt;code&gt;LoopAgent&lt;/code&gt;, and &lt;code&gt;SequentialAgent&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;In &lt;code&gt;streamforge_agent/agent.py&lt;/code&gt;, &lt;code&gt;build_streamforge_event_pipeline()&lt;/code&gt; composes the &lt;code&gt;3&lt;/code&gt; parallel enrichment agents, the iterative quality critic loop, and the schema-constrained publisher agent into a single parent &lt;code&gt;SequentialAgent&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;==&amp;gt; [1/6] Enabling Cloud Run, Eventarc, Pub/Sub, Storage, and Firestore APIs...
==&amp;gt; [2/6] Creating Cloud Storage Inbox Bucket &amp;amp; Dead-Letter Pub/Sub Topic...
==&amp;gt; [3/6] Creating Least-Privilege Service Accounts...
==&amp;gt; [4/6] Deploying StreamForge ADK Service to Cloud Run (private ingress)...
Service [streamforge-event-adk] revision [streamforge-event-adk-00001-x8k] has been deployed and is serving 100 percent of traffic.
==&amp;gt; [5/6] Granting Cloud Run Invoker + Eventarc EventReceiver to Eventarc SA...
==&amp;gt; [6/6] Creating Eventarc Trigger for google.cloud.storage.object.v1.finalized...
Created trigger [streamforge-gcs-release-trigger] in [us-central1].
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h4&gt;
  
  
  Step 4: Verify the Pipeline and CloudEvent Deduplication Locally
&lt;/h4&gt;

&lt;p&gt;Run &lt;code&gt;scripts/simulate_cloudevent_pipeline.py&lt;/code&gt; to execute the 3-branch &lt;code&gt;ParallelAgent&lt;/code&gt; fan-out, inspect the 2-iteration &lt;code&gt;LoopAgent&lt;/code&gt; self-correction trace, and verify the &lt;code&gt;ce-id&lt;/code&gt; idempotency guard against a duplicate Pub/Sub delivery.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;==&amp;gt; [1/6] Enabling Cloud Run, Eventarc, Pub/Sub, Storage, and Firestore APIs...
==&amp;gt; [2/6] Creating Cloud Storage Inbox Bucket &amp;amp; Dead-Letter Pub/Sub Topic...
==&amp;gt; [3/6] Creating Least-Privilege Service Accounts...
==&amp;gt; [4/6] Deploying StreamForge ADK Service to Cloud Run (private ingress)...
Service [streamforge-event-adk] revision [streamforge-event-adk-00001-x8k] has been deployed and is serving 100 percent of traffic.
==&amp;gt; [5/6] Granting Cloud Run Invoker + Eventarc EventReceiver to Eventarc SA...
==&amp;gt; [6/6] Creating Eventarc Trigger for google.cloud.storage.object.v1.finalized...
Created trigger [streamforge-gcs-release-trigger] in [us-central1].
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;==&amp;gt; [1/6] Enabling Cloud Run, Eventarc, Pub/Sub, Storage, and Firestore APIs...
==&amp;gt; [2/6] Creating Cloud Storage Inbox Bucket &amp;amp; Dead-Letter Pub/Sub Topic...
==&amp;gt; [3/6] Creating Least-Privilege Service Accounts...
==&amp;gt; [4/6] Deploying StreamForge ADK Service to Cloud Run (private ingress)...
Service [streamforge-event-adk] revision [streamforge-event-adk-00001-x8k] has been deployed and is serving 100 percent of traffic.
==&amp;gt; [5/6] Granting Cloud Run Invoker + Eventarc EventReceiver to Eventarc SA...
==&amp;gt; [6/6] Creating Eventarc Trigger for google.cloud.storage.object.v1.finalized...
Created trigger [streamforge-gcs-release-trigger] in [us-central1].
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h4&gt;
  
  
  Step 5: Deploy the Private Cloud Run Receiver and Eventarc Trigger
&lt;/h4&gt;

&lt;p&gt;Run &lt;code&gt;deploy/deploy_eventarc_adk.sh&lt;/code&gt; to deploy the container to &lt;strong&gt;Google Cloud Run&lt;/strong&gt; (&lt;code&gt;2 vCPU&lt;/code&gt;, &lt;code&gt;2 GiB&lt;/code&gt; memory, &lt;code&gt;--no-allow-unauthenticated&lt;/code&gt;, &lt;code&gt;--min-instances=0&lt;/code&gt;, &lt;code&gt;--max-instances=10&lt;/code&gt;) and bind the &lt;strong&gt;Eventarc&lt;/strong&gt; trigger to &lt;code&gt;google.cloud.storage.object.v1.finalized&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;==&amp;gt; [1/6] Enabling Cloud Run, Eventarc, Pub/Sub, Storage, and Firestore APIs...
==&amp;gt; [2/6] Creating Cloud Storage Inbox Bucket &amp;amp; Dead-Letter Pub/Sub Topic...
==&amp;gt; [3/6] Creating Least-Privilege Service Accounts...
==&amp;gt; [4/6] Deploying StreamForge ADK Service to Cloud Run (private ingress)...
Service [streamforge-event-adk] revision [streamforge-event-adk-00001-x8k] has been deployed and is serving 100 percent of traffic.
==&amp;gt; [5/6] Granting Cloud Run Invoker + Eventarc EventReceiver to Eventarc SA...
==&amp;gt; [6/6] Creating Eventarc Trigger for google.cloud.storage.object.v1.finalized...
Created trigger [streamforge-gcs-release-trigger] in [us-central1].
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;==&amp;gt; [1/6] Enabling Cloud Run, Eventarc, Pub/Sub, Storage, and Firestore APIs...
==&amp;gt; [2/6] Creating Cloud Storage Inbox Bucket &amp;amp; Dead-Letter Pub/Sub Topic...
==&amp;gt; [3/6] Creating Least-Privilege Service Accounts...
==&amp;gt; [4/6] Deploying StreamForge ADK Service to Cloud Run (private ingress)...
Service [streamforge-event-adk] revision [streamforge-event-adk-00001-x8k] has been deployed and is serving 100 percent of traffic.
==&amp;gt; [5/6] Granting Cloud Run Invoker + Eventarc EventReceiver to Eventarc SA...
==&amp;gt; [6/6] Creating Eventarc Trigger for google.cloud.storage.object.v1.finalized...
Created trigger [streamforge-gcs-release-trigger] in [us-central1].
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h4&gt;
  
  
  Official Google Cloud and ADK Documentation
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://google.github.io/adk-docs/" rel="noopener noreferrer"&gt;Google Agent Development Kit (ADK) Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://google.github.io/adk-docs/agents/workflow-agents/" rel="noopener noreferrer"&gt;Google ADK Workflow Agents (&lt;code&gt;SequentialAgent&lt;/code&gt;, &lt;code&gt;ParallelAgent&lt;/code&gt;, &lt;code&gt;LoopAgent&lt;/code&gt;)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/google/adk-python" rel="noopener noreferrer"&gt;Google ADK Python SDK Repository (&lt;code&gt;google/adk-python&lt;/code&gt;)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://cloud.google.com/vertex-ai/generative-ai/docs/open-models/use-gemma" rel="noopener noreferrer"&gt;Google Gemma Open Models Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://cloud.google.com/eventarc/docs" rel="noopener noreferrer"&gt;Google Cloud Eventarc Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://cloud.google.com/run/docs" rel="noopener noreferrer"&gt;Google Cloud Run Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://cloud.google.com/pubsub/docs/push" rel="noopener noreferrer"&gt;Google Cloud Pub/Sub Push Subscriptions Guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://cloud.google.com/firestore/docs" rel="noopener noreferrer"&gt;Google Cloud Firestore Documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h4&gt;
  
  
  Summary
&lt;/h4&gt;

&lt;p&gt;The goal of this article was to build and verify a real-time, event-driven multi-agent pipeline on Google Cloud using Eventarc, Cloud Pub/Sub, Cloud Run, open-weights Gemma 3, and the Google Agent Development Kit. The key to the solution was pairing &lt;code&gt;ParallelAgent&lt;/code&gt; for concurrent 3-branch fan-out with &lt;code&gt;LoopAgent&lt;/code&gt; for iterative cross-branch self-correction and a Cloud Firestore &lt;code&gt;ce-id&lt;/code&gt; deduplication ledger. The verification results were:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🟢 &lt;strong&gt;Concurrent Fan-Out (&lt;code&gt;ParallelAgent&lt;/code&gt;):&lt;/strong&gt; Extracted engineering specs (&lt;code&gt;73.8%&lt;/code&gt; latency drop from &lt;code&gt;145 ms&lt;/code&gt; to &lt;code&gt;38 ms&lt;/code&gt; at &lt;code&gt;250,000&lt;/code&gt; rows/sec), localized copy across &lt;code&gt;3&lt;/code&gt; locales (&lt;code&gt;en_US&lt;/code&gt;, &lt;code&gt;de_DE&lt;/code&gt;, &lt;code&gt;ja_JP&lt;/code&gt;), and forecasted &lt;code&gt;$2,856,000&lt;/code&gt; in 12-month Net New ARR lift across &lt;code&gt;340&lt;/code&gt; upgraded accounts (&lt;code&gt;18.5%&lt;/code&gt; of &lt;code&gt;1,840&lt;/code&gt; active Growth Tier accounts at &lt;code&gt;$8,400&lt;/code&gt; annual expansion).&lt;/li&gt;
&lt;li&gt;🟢 &lt;strong&gt;Self-Correcting Quality Loop (&lt;code&gt;LoopAgent&lt;/code&gt;):&lt;/strong&gt; Detected the &lt;code&gt;€459.08/mo&lt;/code&gt; and &lt;code&gt;¥75,848/mo&lt;/code&gt; currency formatting violations on Iteration &lt;code&gt;1&lt;/code&gt; (&lt;code&gt;quality_score = 0.72&lt;/code&gt;), repaired them to &lt;code&gt;€460/mo&lt;/code&gt; and &lt;code&gt;¥75,800/mo&lt;/code&gt;, and exited cleanly on Iteration &lt;code&gt;2&lt;/code&gt; (&lt;code&gt;quality_score = 1.0&lt;/code&gt;) via &lt;code&gt;exit_quality_loop()&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;🟢 &lt;strong&gt;At-Least-Once Idempotency:&lt;/strong&gt; Short-circuited duplicate &lt;code&gt;ce-98104271-gcs-finalized&lt;/code&gt; redelivery in &lt;code&gt;&amp;lt; 5 ms&lt;/code&gt; with &lt;code&gt;0&lt;/code&gt; redundant parallel branches or LLM calls.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The strategy for orchestrating event-driven multi-agent pipelines with Google ADK and Gemma 3 on Cloud Run was validated with an incremental step by step approach.&lt;/p&gt;

</description>
      <category>buildmultiagents</category>
      <category>adk</category>
      <category>googleai</category>
      <category>python</category>
    </item>
    <item>
      <title>Building Production-Ready Open-Weights AI Agents with Gemma, Google ADK, and Cloud Run GPUs</title>
      <dc:creator>Robina Mirbahar</dc:creator>
      <pubDate>Fri, 16 Oct 2026 16:43:29 +0000</pubDate>
      <link>https://dev.to/gde/building-production-ready-open-weights-ai-agents-with-gemma-google-adk-and-cloud-run-gpus-2mfg</link>
      <guid>https://dev.to/gde/building-production-ready-open-weights-ai-agents-with-gemma-google-adk-and-cloud-run-gpus-2mfg</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%2F6gs5po3c5vkx1racz4eo.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6gs5po3c5vkx1racz4eo.jpg" alt="Figure 1: The 4 Architectural Pillars of the Gemma Enterprise Agent Platform on Google Cloud" width="800" height="447"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 1: The four foundational pillars I used to take an open-weights Gemma agent from a local prototype to governed enterprise production on Google Cloud.&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;Most AI tutorials stop at a basic "Hello World" chatbot running on a laptop. However, when engineering teams try to move &lt;strong&gt;open-weights models like Google’s Gemma 3 (&lt;code&gt;gemma-3-4b-it&lt;/code&gt;, &lt;code&gt;gemma-3-12b-it&lt;/code&gt;, &lt;code&gt;gemma-3-27b-it&lt;/code&gt;)&lt;/strong&gt; into real enterprise production, they immediately hit four hard engineering questions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Grounding:&lt;/strong&gt; &lt;em&gt;How do I connect Gemma to live enterprise data (like Cloud Firestore) so it doesn't hallucinate?&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Serverless GPU Scaling:&lt;/strong&gt; &lt;em&gt;How do I serve Gemma on GPUs (Cloud Run + vLLM + Cloud Storage FUSE) so it scales to zero when idle instead of burning thousands of dollars a month?&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reliability &amp;amp; Governance:&lt;/strong&gt; &lt;em&gt;How do I guarantee the agent cannot pass malformed tool parameters or accidentally take down a production service?&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Testing &amp;amp; Optimization:&lt;/strong&gt; &lt;em&gt;How do I unit-test an AI agent's tool calls in CI/CD, and how do I fine-tune a small, fast Gemma 4B model with LoRA on Vertex AI so it performs like a 27B model?&lt;/em&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I wrote this article to serve as a complete, end-to-end &lt;strong&gt;Enterprise Reference Blueprint&lt;/strong&gt; that answers all four questions using a single, working project (&lt;strong&gt;CloudGuard&lt;/strong&gt;) verified in Google Cloud Shell (all working code is available in my &lt;a href="https://github.com/RobinaMirbahar/cloudguard-gemma-agent" rel="noopener noreferrer"&gt;&lt;strong&gt;cloudguard-gemma-agent GitHub repository&lt;/strong&gt;&lt;/a&gt;).&lt;/p&gt;
&lt;h3&gt;
  
  
  Where This Blueprint Is Useful in Production
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;DevOps, SRE &amp;amp; Automated Incident Response:&lt;/strong&gt; On-call engineers often waste 20-30 minutes during an outage manually querying logs, searching old postmortems, and finding remediation runbooks. CloudGuard automatically pulls live incident telemetry from Cloud Firestore (&lt;code&gt;get_service_incident&lt;/code&gt;), matches symptoms against historical postmortems in its &lt;strong&gt;Long-Term Memory Bank&lt;/strong&gt; (&lt;code&gt;MEM-2026-014&lt;/code&gt;), and executes approved mitigations in staging (&lt;code&gt;mitigate_runaway_workload&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cloud FinOps &amp;amp; GPU Quota Governance:&lt;/strong&gt; A single misconfigured ML batch job or unthrottled retry loop can spin up dozens of GPUs overnight. CloudGuard checks real-time regional GPU utilization (&lt;code&gt;NVIDIA L4&lt;/code&gt; and &lt;code&gt;RTX PRO 6000&lt;/code&gt;) and monthly budget burn (&lt;code&gt;check_gpu_quota_and_cost&lt;/code&gt;), immediately scaling down runaway staging workloads and calculating hourly dollar savings (&lt;code&gt;$36.12/hr&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Regulated Enterprises Requiring Data Sovereignty (Banking, Healthcare, Government, FinOps):&lt;/strong&gt; Organizations prohibited from sending application telemetry logs, credentials, or infrastructure schemas to external third-party APIs can deploy open-weights Gemma inside their own Google Cloud project behind &lt;code&gt;--no-allow-unauthenticated&lt;/code&gt; service and &lt;strong&gt;Model Armor&lt;/strong&gt; guardrails (&lt;code&gt;cloudguard_agent/guardrails.py&lt;/code&gt;), where accidentally pasted GCP API keys (&lt;code&gt;AIza...&lt;/code&gt;) are redacted &lt;em&gt;before&lt;/em&gt; reaching the model.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AI Engineering &amp;amp; MLOps CI/CD Pipelines:&lt;/strong&gt; Instead of relying on manual "vibe checks" when prompts or tools change, my &lt;strong&gt;ADK Eval&lt;/strong&gt; harness (&lt;code&gt;scripts/run_eval.py&lt;/code&gt;) scores &lt;strong&gt;Tool Trajectory Accuracy (&lt;code&gt;1.00&lt;/code&gt;)&lt;/strong&gt; and &lt;strong&gt;Response Factuality (&lt;code&gt;1.00&lt;/code&gt;)&lt;/strong&gt; on every build, while my &lt;strong&gt;Vertex AI QLoRA&lt;/strong&gt; pipeline (&lt;code&gt;scripts/prepare_and_verify_lora.py&lt;/code&gt;) lets teams replace a 54 GB VRAM model (&lt;code&gt;Gemma 27B&lt;/code&gt;) with an 8.9 GB VRAM model (&lt;code&gt;Gemma 4B + LoRA&lt;/code&gt;) running in ~51ms on a single NVIDIA L4 GPU.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here are the six stages of the production lifecycle I will walk through:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Build:&lt;/strong&gt; Scaffolding a model-agnostic &lt;strong&gt;Google ADK&lt;/strong&gt; agent in Python that runs against local Gemma weights (via Ollama) during development and seamlessly switches to &lt;strong&gt;Cloud Run GPUs&lt;/strong&gt; or &lt;strong&gt;Vertex AI Model Garden&lt;/strong&gt; in production.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Connect:&lt;/strong&gt; Authoring native Python function-calling tools backed by &lt;strong&gt;Cloud Firestore&lt;/strong&gt; to inspect live production incidents and regional GPU FinOps quotas.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scale:&lt;/strong&gt; Deploying &lt;strong&gt;vLLM&lt;/strong&gt; on &lt;strong&gt;Cloud Run Serverless GPUs (&lt;code&gt;NVIDIA L4&lt;/code&gt; / &lt;code&gt;RTX PRO 6000&lt;/code&gt;)&lt;/strong&gt; with &lt;strong&gt;Cloud Storage FUSE&lt;/strong&gt; for zero-download weight streaming, paired with &lt;strong&gt;Short-Term Session State&lt;/strong&gt; and a &lt;strong&gt;Long-Term Memory Bank&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Govern:&lt;/strong&gt; Enforcing deterministic parameter validation with private Cloud Run service configurations, &lt;strong&gt;Model Armor&lt;/strong&gt; parameter formatting (&lt;code&gt;before_model_callback&lt;/code&gt;), and deterministic RBAC tool policies (&lt;code&gt;before_tool_callback&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Optimize:&lt;/strong&gt; Automating CI/CD release gates with &lt;strong&gt;ADK Eval&lt;/strong&gt; (&lt;code&gt;tool_trajectory_avg_score&lt;/code&gt; and &lt;code&gt;response_match_score&lt;/code&gt;) and &lt;strong&gt;OpenTelemetry&lt;/strong&gt; tracing for &lt;strong&gt;Google Cloud Trace&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Specialize:&lt;/strong&gt; Fine-tuning a compact &lt;strong&gt;&lt;code&gt;google/gemma-3-4b-it&lt;/code&gt;&lt;/strong&gt; model using &lt;strong&gt;QLoRA on Vertex AI&lt;/strong&gt; so it matches &lt;strong&gt;&lt;code&gt;gemma-3-27b-it&lt;/code&gt;&lt;/strong&gt; tool-calling accuracy (&lt;code&gt;1.00&lt;/code&gt;) at &lt;strong&gt;2.8x faster latency and 6x lower GPU memory&lt;/strong&gt;.&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%2F1dalil90idh9hjyg2n27.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1dalil90idh9hjyg2n27.jpg" alt="Figure 2: CloudGuard End-to-End Request Flow Architecture" width="800" height="447"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 2: End-to-end request lifecycle for my CloudGuard Incident &amp;amp; FinOps Agent across Cloud Run, vLLM, Cloud Firestore, Model Armor guardrails, and Cloud Trace.&lt;/em&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  Part 1: Platform Foundations &amp;amp; Scaffolding the First Gemma Agent
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Prerequisites &amp;amp; Google Cloud Setup
&lt;/h3&gt;

&lt;p&gt;To follow along with my setup, you will need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;Google Cloud Project&lt;/strong&gt; with billing enabled.&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;Google Cloud SDK (&lt;code&gt;gcloud&lt;/code&gt;)&lt;/strong&gt; installed and authenticated.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Python 3.10+&lt;/strong&gt; and &lt;strong&gt;&lt;a href="https://docs.astral.sh/uv/" rel="noopener noreferrer"&gt;&lt;code&gt;uv&lt;/code&gt;&lt;/a&gt;&lt;/strong&gt; (the fast Python package and virtual environment manager I use across this project).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ollama&lt;/strong&gt; installed locally (&lt;code&gt;ollama pull gemma3:4b&lt;/code&gt; or &lt;code&gt;ollama pull gemma3:27b&lt;/code&gt;) for zero-cost local prototyping before deploying to Google Cloud GPUs.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;First, I set my project and region environment variables and enabled the required Google Cloud APIs:&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;export &lt;/span&gt;&lt;span class="nv"&gt;PROJECT_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;gcloud config get-value project&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;REGION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"us-central1"&lt;/span&gt;

gcloud run services delete cloudguard-adk-agent &lt;span class="nt"&gt;--region&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;REGION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;--quiet&lt;/span&gt;
gcloud run services delete gemma-vllm-service &lt;span class="nt"&gt;--region&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;REGION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;--quiet&lt;/span&gt;
gcloud storage &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;--recursive&lt;/span&gt; gs://&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;PROJECT_ID&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="nt"&gt;-gemma-weights&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, I configured Application Default Credentials (ADC) so my local Python environment can authenticate with Google Cloud services:&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;export &lt;/span&gt;&lt;span class="nv"&gt;PROJECT_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;gcloud config get-value project&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;REGION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"us-central1"&lt;/span&gt;

gcloud run services delete cloudguard-adk-agent &lt;span class="nt"&gt;--region&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;REGION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;--quiet&lt;/span&gt;
gcloud run services delete gemma-vllm-service &lt;span class="nt"&gt;--region&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;REGION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;--quiet&lt;/span&gt;
gcloud storage &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;--recursive&lt;/span&gt; gs://&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;PROJECT_ID&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="nt"&gt;-gemma-weights&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Scaffolding the Project (Local or 1-Click in Google Cloud Shell)
&lt;/h3&gt;

&lt;p&gt;You can either clone and run this project directly inside &lt;strong&gt;Google Cloud Shell&lt;/strong&gt; (which comes pre-authenticated with &lt;code&gt;gcloud&lt;/code&gt; and Python in your browser) by clicking &lt;a href="https://shell.cloud.google.com/?cloudshell_git_repo=https://github.com/RobinaMirbahar/cloudguard-gemma-agent" rel="noopener noreferrer"&gt;&lt;strong&gt;Open in Google Cloud Shell&lt;/strong&gt;&lt;/a&gt;, or initialize the workspace locally with &lt;code&gt;uv&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%2Fv1ka4amik4gu2t2somfa.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%2Fv1ka4amik4gu2t2somfa.png" alt="Cloning the CloudGuard Gemma Agent repository directly into Google Cloud Shell" width="800" height="391"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Step 1: Launching the &lt;a href="https://github.com/RobinaMirbahar/cloudguard-gemma-agent" rel="noopener noreferrer"&gt;&lt;code&gt;RobinaMirbahar/cloudguard-gemma-agent&lt;/code&gt;&lt;/a&gt; repository directly inside Google Cloud Shell.&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%2Fxbuiuzb14b794726bitz.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%2Fxbuiuzb14b794726bitz.png" alt="Authorizing Google Cloud Shell to access Google Cloud API credentials" width="800" height="393"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Step 2: Authorizing Google Cloud Shell credentials while the repository clones into the Cloud Shell workspace.&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%2Fiku0gbwfyla3wex4ey4v.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%2Fiku0gbwfyla3wex4ey4v.png" alt="Running the CloudGuard setup and verification commands inside Google Cloud Shell Editor" width="800" height="396"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Step 3: Executing the CloudGuard environment setup, database seeding, and ADK evaluation commands inside the Google Cloud Shell terminal.&lt;/em&gt;&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;export &lt;/span&gt;&lt;span class="nv"&gt;PROJECT_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;gcloud config get-value project&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;REGION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"us-central1"&lt;/span&gt;

gcloud run services delete cloudguard-adk-agent &lt;span class="nt"&gt;--region&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;REGION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;--quiet&lt;/span&gt;
gcloud run services delete gemma-vllm-service &lt;span class="nt"&gt;--region&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;REGION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;--quiet&lt;/span&gt;
gcloud storage &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;--recursive&lt;/span&gt; gs://&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;PROJECT_ID&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="nt"&gt;-gemma-weights&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I structured the repository so that agent orchestration, native tools, memory management, validation callbacks, and evaluation suites are cleanly separated (and runnable offline via a deterministic local simulation harness before touching cloud GPUs):&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;export &lt;/span&gt;&lt;span class="nv"&gt;PROJECT_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;gcloud config get-value project&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;REGION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"us-central1"&lt;/span&gt;

gcloud run services delete cloudguard-adk-agent &lt;span class="nt"&gt;--region&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;REGION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;--quiet&lt;/span&gt;
gcloud run services delete gemma-vllm-service &lt;span class="nt"&gt;--region&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;REGION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;--quiet&lt;/span&gt;
gcloud storage &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;--recursive&lt;/span&gt; gs://&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;PROJECT_ID&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="nt"&gt;-gemma-weights&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%2Fjwe029rist0mify4abjv.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%2Fjwe029rist0mify4abjv.png" alt="Repository structure of cloudguard-gemma-agent on GitHub" width="800" height="396"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Repository structure of &lt;a href="https://github.com/RobinaMirbahar/cloudguard-gemma-agent" rel="noopener noreferrer"&gt;&lt;code&gt;RobinaMirbahar/cloudguard-gemma-agent&lt;/code&gt;&lt;/a&gt; showing the modular separation across agent orchestration, Firestore tools, memory, guardrails, deployment manifests, and evaluation scripts.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In &lt;code&gt;pyproject.toml&lt;/code&gt;, I declared &lt;code&gt;google-adk&lt;/code&gt;, &lt;code&gt;litellm&lt;/code&gt;, &lt;code&gt;google-cloud-firestore&lt;/code&gt;, and &lt;code&gt;opentelemetry-sdk&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;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;PROJECT_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;gcloud config get-value project&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;REGION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"us-central1"&lt;/span&gt;

gcloud run services delete cloudguard-adk-agent &lt;span class="nt"&gt;--region&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;REGION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;--quiet&lt;/span&gt;
gcloud run services delete gemma-vllm-service &lt;span class="nt"&gt;--region&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;REGION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;--quiet&lt;/span&gt;
gcloud storage &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;--recursive&lt;/span&gt; gs://&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;PROJECT_ID&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="nt"&gt;-gemma-weights&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then I locked and installed the dependencies:&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;export &lt;/span&gt;&lt;span class="nv"&gt;PROJECT_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;gcloud config get-value project&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;REGION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"us-central1"&lt;/span&gt;

gcloud run services delete cloudguard-adk-agent &lt;span class="nt"&gt;--region&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;REGION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;--quiet&lt;/span&gt;
gcloud run services delete gemma-vllm-service &lt;span class="nt"&gt;--region&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;REGION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;--quiet&lt;/span&gt;
gcloud storage &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;--recursive&lt;/span&gt; gs://&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;PROJECT_ID&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="nt"&gt;-gemma-weights&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Decoupling Local vs. Cloud GPU Inference (&lt;code&gt;.env.example&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;One of the strongest architectural benefits of &lt;strong&gt;Google ADK&lt;/strong&gt; is its model-agnostic &lt;code&gt;LiteLlm&lt;/code&gt; integration. By defining a &lt;code&gt;.env&lt;/code&gt; configuration file, I can point my agent to a local Ollama server on &lt;code&gt;localhost:11434&lt;/code&gt; during development and switch to a self-hosted &lt;strong&gt;vLLM&lt;/strong&gt; endpoint on &lt;strong&gt;Cloud Run GPUs&lt;/strong&gt; (or &lt;strong&gt;Vertex AI Model Garden&lt;/strong&gt;) in production without changing a single line of agent orchestration code:&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;export &lt;/span&gt;&lt;span class="nv"&gt;PROJECT_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;gcloud config get-value project&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;REGION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"us-central1"&lt;/span&gt;

gcloud run services delete cloudguard-adk-agent &lt;span class="nt"&gt;--region&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;REGION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;--quiet&lt;/span&gt;
gcloud run services delete gemma-vllm-service &lt;span class="nt"&gt;--region&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;REGION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;--quiet&lt;/span&gt;
gcloud storage &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;--recursive&lt;/span&gt; gs://&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;PROJECT_ID&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="nt"&gt;-gemma-weights&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Defining the CloudGuard Agent Persona (&lt;code&gt;cloudguard_agent/agent.py&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;When building agents with open-weights models like Gemma, &lt;strong&gt;explicit, numbered system instructions&lt;/strong&gt; are essential. Here is how I defined the agent's identity, tool bindings, and strict operational constraints in &lt;code&gt;cloudguard_agent/agent.py&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;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;PROJECT_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;gcloud config get-value project&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;REGION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"us-central1"&lt;/span&gt;

gcloud run services delete cloudguard-adk-agent &lt;span class="nt"&gt;--region&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;REGION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;--quiet&lt;/span&gt;
gcloud run services delete gemma-vllm-service &lt;span class="nt"&gt;--region&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;REGION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;--quiet&lt;/span&gt;
gcloud storage &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;--recursive&lt;/span&gt; gs://&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;PROJECT_ID&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="nt"&gt;-gemma-weights&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Part 2: Native Python Tools &amp;amp; Connecting to Cloud Firestore
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fiemv8fg1sb7q2ow67yn1.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fiemv8fg1sb7q2ow67yn1.jpg" alt="Figure 3: Part 2 - ADK Native Function Calling &amp;amp; Cloud Firestore Integration" width="800" height="447"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 3: How Google ADK introspects my Python type hints and docstrings to drive structured Gemma tool calls against Cloud Firestore.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;An isolated LLM knows nothing about active Cloud Run services, operational SRE runbooks, or current monthly GPU FinOps burn rates. To bridge that gap, &lt;strong&gt;Google ADK&lt;/strong&gt; automatically converts standard Python functions into JSON Schema tool definitions for Gemma.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;My Engineering Rule for Open-Weights Gemma:&lt;/strong&gt; Compact open-weights models (&lt;code&gt;Gemma 4B&lt;/code&gt;, &lt;code&gt;12B&lt;/code&gt;, &lt;code&gt;27B&lt;/code&gt;) rely heavily on explicit &lt;code&gt;Args:&lt;/code&gt; descriptions and concrete format examples (such as &lt;code&gt;'INC-YYYY-NNNN'&lt;/code&gt;) in Python docstrings to construct valid JSON tool arguments. I treat Python docstrings as first-class prompt engineering.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;
  
  
  Implementing the Operational Tools (&lt;code&gt;cloudguard_agent/tools.py&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;I built four native Python tools backed by &lt;strong&gt;Cloud Firestore&lt;/strong&gt; (plus a zero-config local JSON schema mirror (&lt;code&gt;USE_LOCAL_MOCK_DB="true"&lt;/code&gt;) so the entire test suite can be verified locally before provisioning cloud resources):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;get_service_incident(incident_id: str)&lt;/code&gt;: Retrieves severity, symptom, GPU type, hourly USD burn rate, and remediation runbook for a specific incident ticket.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;list_active_alerts(environment: str = "all")&lt;/code&gt;: Lists open incidents filtered by &lt;code&gt;production&lt;/code&gt;, &lt;code&gt;staging&lt;/code&gt;, or &lt;code&gt;all&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;check_gpu_quota_and_cost(region: str)&lt;/code&gt;: Checks regional NVIDIA L4 and RTX PRO 6000 quota limits, active usage, and monthly FinOps budget percentage.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;mitigate_runaway_workload(...)&lt;/code&gt;: Scales down a runaway Cloud Run service or batch job and records the hourly cost savings.
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;PROJECT_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;gcloud config get-value project&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;REGION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"us-central1"&lt;/span&gt;

gcloud run services delete cloudguard-adk-agent &lt;span class="nt"&gt;--region&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;REGION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;--quiet&lt;/span&gt;
gcloud run services delete gemma-vllm-service &lt;span class="nt"&gt;--region&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;REGION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;--quiet&lt;/span&gt;
gcloud storage &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;--recursive&lt;/span&gt; gs://&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;PROJECT_ID&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="nt"&gt;-gemma-weights&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Seeding the Database (&lt;code&gt;scripts/seed_firestore.py&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;When connecting to a live Cloud Firestore instance in Google Cloud, you can provision the database in Native mode:&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;export &lt;/span&gt;&lt;span class="nv"&gt;PROJECT_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;gcloud config get-value project&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;REGION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"us-central1"&lt;/span&gt;

gcloud run services delete cloudguard-adk-agent &lt;span class="nt"&gt;--region&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;REGION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;--quiet&lt;/span&gt;
gcloud run services delete gemma-vllm-service &lt;span class="nt"&gt;--region&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;REGION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;--quiet&lt;/span&gt;
gcloud storage &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;--recursive&lt;/span&gt; gs://&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;PROJECT_ID&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="nt"&gt;-gemma-weights&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I then ran &lt;code&gt;scripts/seed_firestore.py&lt;/code&gt; to populate the &lt;code&gt;incidents&lt;/code&gt; and &lt;code&gt;quotas&lt;/code&gt; collections:&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;export &lt;/span&gt;&lt;span class="nv"&gt;PROJECT_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;gcloud config get-value project&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;REGION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"us-central1"&lt;/span&gt;

gcloud run services delete cloudguard-adk-agent &lt;span class="nt"&gt;--region&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;REGION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;--quiet&lt;/span&gt;
gcloud run services delete gemma-vllm-service &lt;span class="nt"&gt;--region&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;REGION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;--quiet&lt;/span&gt;
gcloud storage &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;--recursive&lt;/span&gt; gs://&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;PROJECT_ID&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="nt"&gt;-gemma-weights&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here is the terminal output from running the database seeder:&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;export &lt;/span&gt;&lt;span class="nv"&gt;PROJECT_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;gcloud config get-value project&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;REGION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"us-central1"&lt;/span&gt;

gcloud run services delete cloudguard-adk-agent &lt;span class="nt"&gt;--region&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;REGION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;--quiet&lt;/span&gt;
gcloud run services delete gemma-vllm-service &lt;span class="nt"&gt;--region&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;REGION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;--quiet&lt;/span&gt;
gcloud storage &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;--recursive&lt;/span&gt; gs://&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;PROJECT_ID&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="nt"&gt;-gemma-weights&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%2Fzlvaslcun5345ekvllt5.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%2Fzlvaslcun5345ekvllt5.png" alt="Live Google Cloud Shell output showing the seeded incidents and regional GPU FinOps quota collections" width="800" height="366"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Running &lt;code&gt;scripts/seed_firestore.py&lt;/code&gt; inside Google Cloud Shell to populate the &lt;code&gt;incidents&lt;/code&gt; and &lt;code&gt;quotas&lt;/code&gt; collections.&lt;/em&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  Part 3: Scaling with Cloud Run Serverless GPUs, Vertex AI Model Garden &amp;amp; Dual Memory
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpb401fwu9faq8eecbjzd.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpb401fwu9faq8eecbjzd.jpg" alt="Figure 4: Part 3 - Serverless GPU Scaling on Cloud Run &amp;amp; Dual Memory Architecture" width="800" height="447"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 4: Streaming Gemma weights from Cloud Storage FUSE into Cloud Run Serverless GPUs with vLLM, backed by Short-Term Session State and a Long-Term Enterprise Memory Bank.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Moving an open-weights Gemma model from a developer laptop into enterprise production on Google Cloud offers two primary deployment patterns: &lt;strong&gt;&lt;a href="https://cloud.google.com/run/docs/configuring/services/gpu" rel="noopener noreferrer"&gt;Cloud Run Serverless GPUs&lt;/a&gt; with vLLM&lt;/strong&gt; (for scale-to-zero serverless containers) or &lt;strong&gt;&lt;a href="https://cloud.google.com/model-garden" rel="noopener noreferrer"&gt;Vertex AI Model Garden&lt;/a&gt;&lt;/strong&gt; (for one-call managed GPU endpoints).&lt;/p&gt;
&lt;h3&gt;
  
  
  Option A: Serverless GPU Serving on Cloud Run with vLLM &amp;amp; Cloud Storage FUSE
&lt;/h3&gt;

&lt;p&gt;Instead of baking multi-gigabyte model weights into a container image - or downloading them from Hugging Face on every cold start - I stage the Gemma weights in a regional &lt;strong&gt;&lt;a href="https://cloud.google.com/storage" rel="noopener noreferrer"&gt;Google Cloud Storage (GCS)&lt;/a&gt;&lt;/strong&gt; bucket and mount that bucket at &lt;code&gt;/mnt/models&lt;/code&gt; using &lt;strong&gt;&lt;a href="https://cloud.google.com/run/docs/configuring/services/cloud-storage-volume-mounts" rel="noopener noreferrer"&gt;Cloud Storage FUSE&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;VRAM Sizing Note on Google Cloud Run GPUs:&lt;/strong&gt; A single &lt;strong&gt;NVIDIA L4 GPU&lt;/strong&gt; on Cloud Run provides &lt;strong&gt;24 GB of VRAM&lt;/strong&gt;, which easily fits &lt;code&gt;google/gemma-3-4b-it&lt;/code&gt; (~8.4 GB in &lt;code&gt;bfloat16&lt;/code&gt;), &lt;code&gt;google/gemma-3-12b-it&lt;/code&gt;, or a 4-bit AWQ quantized &lt;code&gt;google/gemma-3-27b-it&lt;/code&gt;. To run unquantized &lt;code&gt;bfloat16&lt;/code&gt; &lt;code&gt;google/gemma-3-27b-it&lt;/code&gt; (~54 GB VRAM) on a single serverless instance, use &lt;code&gt;--gpu-type=nvidia-rtx-pro-6000&lt;/code&gt; on Cloud Run or deploy on &lt;a href="https://cloud.google.com/vertex-ai/generative-ai/docs/open-models/use-gemma" rel="noopener noreferrer"&gt;Vertex AI Model Garden&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Here is my &lt;code&gt;deploy/Dockerfile.vllm&lt;/code&gt; configuration:&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;export &lt;/span&gt;&lt;span class="nv"&gt;PROJECT_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;gcloud config get-value project&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;REGION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"us-central1"&lt;/span&gt;

gcloud run services delete cloudguard-adk-agent &lt;span class="nt"&gt;--region&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;REGION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;--quiet&lt;/span&gt;
gcloud run services delete gemma-vllm-service &lt;span class="nt"&gt;--region&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;REGION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;--quiet&lt;/span&gt;
gcloud storage &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;--recursive&lt;/span&gt; gs://&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;PROJECT_ID&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="nt"&gt;-gemma-weights&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And here is the &lt;code&gt;gcloud run deploy&lt;/code&gt; command from &lt;code&gt;deploy/deploy_cloud_run_gpu.sh&lt;/code&gt; mounting the GCS FUSE volume:&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;export &lt;/span&gt;&lt;span class="nv"&gt;PROJECT_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;gcloud config get-value project&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;REGION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"us-central1"&lt;/span&gt;

gcloud run services delete cloudguard-adk-agent &lt;span class="nt"&gt;--region&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;REGION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;--quiet&lt;/span&gt;
gcloud run services delete gemma-vllm-service &lt;span class="nt"&gt;--region&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;REGION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;--quiet&lt;/span&gt;
gcloud storage &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;--recursive&lt;/span&gt; gs://&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;PROJECT_ID&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="nt"&gt;-gemma-weights&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Option B: Managed Deployment via Vertex AI Model Garden
&lt;/h3&gt;

&lt;p&gt;Alternatively, if you prefer a managed endpoint provisioned directly from &lt;strong&gt;&lt;a href="https://cloud.google.com/model-garden" rel="noopener noreferrer"&gt;Vertex AI Model Garden&lt;/a&gt;&lt;/strong&gt;, you can deploy &lt;code&gt;google/gemma3@gemma-3-4b-it&lt;/code&gt; or &lt;code&gt;google/gemma3@gemma-3-27b-it&lt;/code&gt; programmatically using the &lt;a href="https://cloud.google.com/vertex-ai/generative-ai/docs/open-models/use-gemma" rel="noopener noreferrer"&gt;Vertex AI Python SDK&lt;/a&gt;:&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;export &lt;/span&gt;&lt;span class="nv"&gt;PROJECT_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;gcloud config get-value project&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;REGION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"us-central1"&lt;/span&gt;

gcloud run services delete cloudguard-adk-agent &lt;span class="nt"&gt;--region&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;REGION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;--quiet&lt;/span&gt;
gcloud run services delete gemma-vllm-service &lt;span class="nt"&gt;--region&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;REGION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;--quiet&lt;/span&gt;
gcloud storage &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;--recursive&lt;/span&gt; gs://&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;PROJECT_ID&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="nt"&gt;-gemma-weights&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Dual-Tier Memory: Short-Term Session State vs. Long-Term Memory Bank
&lt;/h3&gt;

&lt;p&gt;In &lt;code&gt;cloudguard_agent/memory.py&lt;/code&gt;, I equipped the agent with two distinct memory layers:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Short-Term Conversational Session (&lt;code&gt;AgentSessionState&lt;/code&gt;):&lt;/strong&gt; Tracks the active incident ID (&lt;code&gt;active_incident_id&lt;/code&gt;) within the current troubleshooting thread. When an engineer inspects &lt;code&gt;INC-2026-0891&lt;/code&gt; in Turn 2 and says &lt;em&gt;"Go ahead and mitigate that runaway staging workload"&lt;/em&gt; in Turn 4, the agent resolves the reference automatically.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Long-Term Organizational Memory (&lt;code&gt;EnterpriseMemoryBank&lt;/code&gt;):&lt;/strong&gt; Stores verified postmortem learnings across all sessions. When &lt;code&gt;INC-2026-0891&lt;/code&gt; triggers on &lt;code&gt;ml-batch-indexer-dev&lt;/code&gt;, the agent automatically searches historical postmortems and retrieves &lt;code&gt;MEM-2026-014&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here is the execution output from running my multi-turn simulation harness (&lt;code&gt;uv run python scripts/simulate_parts.py&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;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;PROJECT_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;gcloud config get-value project&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;REGION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"us-central1"&lt;/span&gt;

gcloud run services delete cloudguard-adk-agent &lt;span class="nt"&gt;--region&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;REGION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;--quiet&lt;/span&gt;
gcloud run services delete gemma-vllm-service &lt;span class="nt"&gt;--region&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;REGION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;--quiet&lt;/span&gt;
gcloud storage &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;--recursive&lt;/span&gt; gs://&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;PROJECT_ID&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="nt"&gt;-gemma-weights&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%2Fghhxu1i1bgcpgqsgemd2.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%2Fghhxu1i1bgcpgqsgemd2.png" alt="Live Google Cloud Shell execution of the 4-turn incident triage, FinOps GPU quota check, and session-aware mitigation workflow" width="800" height="367"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Live execution of &lt;code&gt;scripts/simulate_parts.py&lt;/code&gt; in Google Cloud Shell showing multi-turn tool calling, Long-Term Memory Bank matching (&lt;code&gt;MEM-2026-014&lt;/code&gt;), and Short-Term Session State mitigation.&lt;/em&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  Part 4: Deterministic Input Formatting &amp;amp; Tool Parameter Validation
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F121zmksyp7vl2i211gi5.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F121zmksyp7vl2i211gi5.jpg" alt="Figure 5: Part 4 - Deterministic Input &amp;amp; Parameter Validation Callbacks" width="800" height="447"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 5: Three sequential validation gates I implemented to protect the CloudGuard agent: Cloud Run service routing, Before-Model parameter formatting &amp;amp; injection blocking, and Before-Tool RBAC enforcement.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Giving an AI agent write-access to infrastructure requires deterministic validation boundaries. Telling an LLM &lt;em&gt;"Never scale down production"&lt;/em&gt; inside a system prompt is a probabilistic guideline - not an enterprise reliability control.&lt;/p&gt;

&lt;p&gt;I implemented defense-in-depth across three sequential gates:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Gate 1: Service-to-Service Cloud Run Routing:&lt;/strong&gt; The &lt;code&gt;gemma-vllm-service&lt;/code&gt; is configured with &lt;code&gt;--no-allow-unauthenticated&lt;/code&gt;. Only the ADK orchestrator's service account (&lt;code&gt;cloudguard-agent-sa&lt;/code&gt;) holds &lt;code&gt;roles/run.invoker&lt;/code&gt; permission.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gate 2: Before-Model Input Sanitization (&lt;code&gt;inspect_and_sanitize_prompt&lt;/code&gt;):&lt;/strong&gt; Modeled on &lt;strong&gt;Google Cloud Model Armor&lt;/strong&gt;, this interceptor scans every incoming prompt for adversarial jailbreak signatures and automatically redacts live credentials (such as &lt;code&gt;AIza...&lt;/code&gt; GCP API keys or &lt;code&gt;ya29...&lt;/code&gt; bearer tokens) &lt;em&gt;before&lt;/em&gt; they reach the Gemma model or telemetry logs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gate 3: Before-Tool Deterministic RBAC (&lt;code&gt;validate_tool_invocation&lt;/code&gt;):&lt;/strong&gt; Intercepts every &lt;code&gt;mitigate_runaway_workload&lt;/code&gt; call before Python executes it, blocking any &lt;code&gt;production&lt;/code&gt; mutation unless the caller holds &lt;code&gt;sre-incident-commander&lt;/code&gt; privileges (&lt;code&gt;POL-PROD-MUTATION-001&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Guardrail Implementation (&lt;code&gt;cloudguard_agent/guardrails.py&lt;/code&gt;)
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;PROJECT_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;gcloud config get-value project&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;REGION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"us-central1"&lt;/span&gt;

gcloud run services delete cloudguard-adk-agent &lt;span class="nt"&gt;--region&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;REGION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;--quiet&lt;/span&gt;
gcloud run services delete gemma-vllm-service &lt;span class="nt"&gt;--region&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;REGION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;--quiet&lt;/span&gt;
gcloud storage &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;--recursive&lt;/span&gt; gs://&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;PROJECT_ID&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="nt"&gt;-gemma-weights&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Validation Verification Output
&lt;/h3&gt;

&lt;p&gt;Here is the audit trace from testing invalid parameter formatting, unauthorized production scaling, and prompt injection against my guardrails:&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;export &lt;/span&gt;&lt;span class="nv"&gt;PROJECT_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;gcloud config get-value project&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;REGION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"us-central1"&lt;/span&gt;

gcloud run services delete cloudguard-adk-agent &lt;span class="nt"&gt;--region&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;REGION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;--quiet&lt;/span&gt;
gcloud run services delete gemma-vllm-service &lt;span class="nt"&gt;--region&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;REGION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;--quiet&lt;/span&gt;
gcloud storage &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;--recursive&lt;/span&gt; gs://&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;PROJECT_ID&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="nt"&gt;-gemma-weights&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%2Fihfv052wyiz9uv5eu0x7.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%2Fihfv052wyiz9uv5eu0x7.png" alt="Live Google Cloud Shell execution of the Part 4 Model Armor input sanitization and RBAC tool policy guardrails" width="799" height="366"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Live execution of &lt;code&gt;scripts/simulate_parts.py&lt;/code&gt; in Google Cloud Shell verifying live API key redaction (&lt;code&gt;[REDACTED_GCP_API_KEY]&lt;/code&gt;), RBAC production scaling denial (&lt;code&gt;POL-PROD-MUTATION-001&lt;/code&gt;), and Model Armor prompt injection blocking.&lt;/em&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  Part 5: Observability &amp;amp; Deterministic Evaluation (ADK Eval)
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4oow1qgdi3fswjn6xasp.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4oow1qgdi3fswjn6xasp.jpg" alt="Figure 6: Part 5 - Deterministic CI/CD Evaluation (ADK Eval) &amp;amp; OpenTelemetry Tracing" width="800" height="447"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 6: Automated CI/CD evaluation pipeline scoring both Tool Trajectory Accuracy and Response Factuality while exporting OpenTelemetry spans to Google Cloud Trace.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Manual "vibe checks" in a chat UI cannot prevent regressions when prompts, tools, or model weights change. Following &lt;strong&gt;ADK Eval&lt;/strong&gt; best practices, I built &lt;code&gt;scripts/run_eval.py&lt;/code&gt; to evaluate the agent against a golden dataset (&lt;code&gt;tests/eval_dataset.json&lt;/code&gt;) across two quantitative metrics:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Tool Trajectory Score (&lt;code&gt;tool_trajectory_avg_score&lt;/code&gt;):&lt;/strong&gt; Verifies that the agent invoked the exact expected sequence of tools with the exact expected JSON arguments (&lt;code&gt;1.00&lt;/code&gt; = 100% match).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Response Factuality Score (&lt;code&gt;response_match_score&lt;/code&gt;):&lt;/strong&gt; Verifies that required domain identifiers (Incident IDs, runbook codes, dollar savings, or RBAC policy codes) appear in the synthesized response.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Running &lt;code&gt;uv run python scripts/run_eval.py&lt;/code&gt; produces the following evaluation table and &lt;strong&gt;Google Cloud Trace&lt;/strong&gt; OpenTelemetry span:&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;export &lt;/span&gt;&lt;span class="nv"&gt;PROJECT_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;gcloud config get-value project&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;REGION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"us-central1"&lt;/span&gt;

gcloud run services delete cloudguard-adk-agent &lt;span class="nt"&gt;--region&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;REGION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;--quiet&lt;/span&gt;
gcloud run services delete gemma-vllm-service &lt;span class="nt"&gt;--region&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;REGION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;--quiet&lt;/span&gt;
gcloud storage &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;--recursive&lt;/span&gt; gs://&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;PROJECT_ID&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="nt"&gt;-gemma-weights&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%2Fph96oowifyd9uda5vhes.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%2Fph96oowifyd9uda5vhes.png" alt="Live Google Cloud Shell execution of the ADK Deterministic Evaluation Suite (5/5 Passed) and OpenTelemetry Cloud Trace span export" width="800" height="366"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Executing &lt;code&gt;scripts/run_eval.py&lt;/code&gt; in Google Cloud Shell: 5/5 golden test cases passing with a 1.00 Tool Trajectory score and exported OpenTelemetry `gen_ai.&lt;/em&gt;` span.*&lt;/p&gt;


&lt;h2&gt;
  
  
  Part 6: Fine-Tuning Gemma with QLoRA on Vertex AI for Domain Tool Calling
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnmomwkqa31aclr0eads3.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnmomwkqa31aclr0eads3.jpg" alt="Figure 7: Part 6 - Fine-Tuning Gemma with QLoRA on Vertex AI for Domain Tool Calling" width="800" height="447"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 7: End-to-end domain specialization lifecycle - converting verified production traces into a Gemma SFT dataset, training a QLoRA adapter on Vertex AI, and hot-loading it into Cloud Run vLLM.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;While &lt;code&gt;google/gemma-3-27b-it&lt;/code&gt; achieves a &lt;code&gt;1.00&lt;/code&gt; tool-trajectory score out of the box, unquantized &lt;code&gt;bfloat16&lt;/code&gt; weights require ~54 GB of VRAM. To run cleanly on a single 24 GB &lt;strong&gt;NVIDIA L4 GPU&lt;/strong&gt; on Cloud Run with plenty of room for concurrent KV-cache requests, I wanted to specialize the compact &lt;strong&gt;&lt;code&gt;google/gemma-3-4b-it&lt;/code&gt;&lt;/strong&gt; model (which uses only &lt;strong&gt;8.9 GB of VRAM&lt;/strong&gt; and responds in &lt;strong&gt;~51ms&lt;/strong&gt;).&lt;/p&gt;

&lt;p&gt;Using &lt;code&gt;cloudguard_agent/finetuning.py&lt;/code&gt; (&lt;code&gt;uv run python scripts/prepare_and_verify_lora.py&lt;/code&gt;), I exported verified multi-turn tool trajectories into Gemma's official &lt;code&gt;&amp;lt;start_of_turn&amp;gt;&lt;/code&gt; SFT format (&lt;code&gt;data/cloudguard_gemma_sft_train.jsonl&lt;/code&gt;) and generated the &lt;strong&gt;Vertex AI Custom Training (&lt;code&gt;NVIDIA_L4&lt;/code&gt; QLoRA &lt;code&gt;r=16&lt;/code&gt;, &lt;code&gt;lora_alpha=32&lt;/code&gt;)&lt;/strong&gt; specification:&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;export &lt;/span&gt;&lt;span class="nv"&gt;PROJECT_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;gcloud config get-value project&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;REGION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"us-central1"&lt;/span&gt;

gcloud run services delete cloudguard-adk-agent &lt;span class="nt"&gt;--region&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;REGION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;--quiet&lt;/span&gt;
gcloud run services delete gemma-vllm-service &lt;span class="nt"&gt;--region&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;REGION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;--quiet&lt;/span&gt;
gcloud storage &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;--recursive&lt;/span&gt; gs://&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;PROJECT_ID&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="nt"&gt;-gemma-weights&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%2Ftfx6opatsase7lxzn7h1.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%2Ftfx6opatsase7lxzn7h1.png" alt="Live Google Cloud Shell execution showing the exported Gemma SFT tool-calling training example" width="799" height="359"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Live execution in Google Cloud Shell exporting golden SFT trajectories formatted with Gemma's &lt;code&gt;&amp;lt;start_of_turn&amp;gt;&lt;/code&gt; and &lt;code&gt;tool_code&lt;/code&gt; tokens.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Once Vertex AI writes the LoRA adapter weights to &lt;code&gt;gs://${PROJECT_ID}-gemma-weights/adapters/cloudguard-sre-lora-v1&lt;/code&gt;, I hot-load the adapter into vLLM on Cloud Run (&lt;code&gt;--enable-lora --lora-modules cloudguard-sre-lora-v1=/mnt/models/adapters/cloudguard-sre-lora-v1&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;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;PROJECT_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;gcloud config get-value project&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;REGION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"us-central1"&lt;/span&gt;

gcloud run services delete cloudguard-adk-agent &lt;span class="nt"&gt;--region&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;REGION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;--quiet&lt;/span&gt;
gcloud run services delete gemma-vllm-service &lt;span class="nt"&gt;--region&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;REGION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;--quiet&lt;/span&gt;
gcloud storage &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;--recursive&lt;/span&gt; gs://&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;PROJECT_ID&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="nt"&gt;-gemma-weights&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%2Fja2jey5easz1a3d74x07.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%2Fja2jey5easz1a3d74x07.png" alt="Live Google Cloud Shell execution of the Vertex AI QLoRA CustomJob specification and post-tuning ADK Eval benchmark" width="799" height="395"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Live execution inside Google Cloud Shell generating the Vertex AI &lt;code&gt;NVIDIA_L4&lt;/code&gt; QLoRA job specification and verifying the post-tuning ADK Eval benchmark.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;With domain QLoRA fine-tuning, the compact &lt;strong&gt;Gemma 4B&lt;/strong&gt; model matches the &lt;strong&gt;1.00 Tool Trajectory score&lt;/strong&gt; of the 27B model while cutting latency from &lt;strong&gt;144.1ms down to 51.4ms&lt;/strong&gt; and fitting effortlessly on a single Cloud Run &lt;strong&gt;NVIDIA L4 GPU&lt;/strong&gt;.&lt;/p&gt;


&lt;h2&gt;
  
  
  Cleaning Up Cloud Resources (FinOps Hygiene)
&lt;/h2&gt;

&lt;p&gt;If you deploy the Cloud Run GPU services and GCS bucket in your own Google Cloud project, remember to tear them down when finished experimenting:&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;export &lt;/span&gt;&lt;span class="nv"&gt;PROJECT_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;gcloud config get-value project&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;REGION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"us-central1"&lt;/span&gt;

gcloud run services delete cloudguard-adk-agent &lt;span class="nt"&gt;--region&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;REGION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;--quiet&lt;/span&gt;
gcloud run services delete gemma-vllm-service &lt;span class="nt"&gt;--region&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;REGION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;--quiet&lt;/span&gt;
gcloud storage &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;--recursive&lt;/span&gt; gs://&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;PROJECT_ID&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="nt"&gt;-gemma-weights&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Open-Weights Control + Cloud-Native Speed:&lt;/strong&gt; Pairing &lt;strong&gt;Gemma 3&lt;/strong&gt; with &lt;strong&gt;Google ADK&lt;/strong&gt; gives me complete model weight ownership and VPC data residency without sacrificing developer velocity.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Serverless GPU Economics:&lt;/strong&gt; Combining &lt;strong&gt;vLLM&lt;/strong&gt;, &lt;strong&gt;Cloud Run Serverless GPUs (&lt;code&gt;nvidia-l4&lt;/code&gt;)&lt;/strong&gt;, and &lt;strong&gt;Cloud Storage FUSE&lt;/strong&gt; eliminates both idle GPU VM waste and slow container cold starts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deterministic Governance &amp;amp; Evaluation:&lt;/strong&gt; Using &lt;code&gt;before_model_callback&lt;/code&gt;, &lt;code&gt;before_tool_callback&lt;/code&gt;, and &lt;strong&gt;ADK Eval&lt;/strong&gt; turns probabilistic LLM agents into auditable, production-grade software systems.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Companion GitHub Repository
&lt;/h2&gt;

&lt;p&gt;All source code, Dockerfiles, Cloud Run Serverless GPU deployment manifests, golden evaluation datasets, and Vertex AI QLoRA fine-tuning scripts from my tutorial are open-source and available on GitHub:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;GitHub Repository:&lt;/strong&gt; &lt;a href="https://github.com/RobinaMirbahar/cloudguard-gemma-agent" rel="noopener noreferrer"&gt;&lt;strong&gt;github.com/RobinaMirbahar/cloudguard-gemma-agent&lt;/strong&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Core Agent &amp;amp; Orchestrator:&lt;/strong&gt; &lt;a href="https://github.com/RobinaMirbahar/cloudguard-gemma-agent/blob/main/cloudguard_agent/agent.py" rel="noopener noreferrer"&gt;&lt;code&gt;cloudguard_agent/agent.py&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Native Firestore &amp;amp; FinOps Tools:&lt;/strong&gt; &lt;a href="https://github.com/RobinaMirbahar/cloudguard-gemma-agent/blob/main/cloudguard_agent/tools.py" rel="noopener noreferrer"&gt;&lt;code&gt;cloudguard_agent/tools.py&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Input &amp;amp; Tool Parameter Validators:&lt;/strong&gt; &lt;a href="https://github.com/RobinaMirbahar/cloudguard-gemma-agent/blob/main/cloudguard_agent/guardrails.py" rel="noopener noreferrer"&gt;&lt;code&gt;cloudguard_agent/guardrails.py&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ADK Eval &amp;amp; OpenTelemetry Runner:&lt;/strong&gt; &lt;a href="https://github.com/RobinaMirbahar/cloudguard-gemma-agent/blob/main/scripts/run_eval.py" rel="noopener noreferrer"&gt;&lt;code&gt;scripts/run_eval.py&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Vertex AI QLoRA Fine-Tuning:&lt;/strong&gt; &lt;a href="https://github.com/RobinaMirbahar/cloudguard-gemma-agent/blob/main/cloudguard_agent/finetuning.py" rel="noopener noreferrer"&gt;&lt;code&gt;cloudguard_agent/finetuning.py&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Official Google Cloud Documentation &amp;amp; References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Google Gemma Open Models Overview:&lt;/strong&gt; &lt;a href="https://ai.google.dev/gemma" rel="noopener noreferrer"&gt;ai.google.dev/gemma&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Google Agent Development Kit (ADK) Documentation:&lt;/strong&gt; &lt;a href="https://google.github.io/adk-docs/" rel="noopener noreferrer"&gt;google.github.io/adk-docs&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deploying Gemma on Vertex AI Model Garden:&lt;/strong&gt; &lt;a href="https://cloud.google.com/vertex-ai/generative-ai/docs/open-models/use-gemma" rel="noopener noreferrer"&gt;cloud.google.com/vertex-ai/generative-ai/docs/open-models/use-gemma&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cloud Run Serverless GPUs Documentation:&lt;/strong&gt; &lt;a href="https://cloud.google.com/run/docs/configuring/services/gpu" rel="noopener noreferrer"&gt;cloud.google.com/run/docs/configuring/services/gpu&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cloud Storage FUSE Volume Mounts on Cloud Run:&lt;/strong&gt; &lt;a href="https://cloud.google.com/run/docs/configuring/services/cloud-storage-volume-mounts" rel="noopener noreferrer"&gt;cloud.google.com/run/docs/configuring/services/cloud-storage-volume-mounts&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cloud Firestore Native Mode Documentation:&lt;/strong&gt; &lt;a href="https://cloud.google.com/firestore/docs" rel="noopener noreferrer"&gt;cloud.google.com/firestore/docs&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Google Cloud Run Documentation:&lt;/strong&gt; &lt;a href="https://cloud.google.com/run/docs" rel="noopener noreferrer"&gt;cloud.google.com/run/docs&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ADK Deterministic Agent Evaluation (ADK Eval):&lt;/strong&gt; &lt;a href="https://google.github.io/adk-docs/evaluate/" rel="noopener noreferrer"&gt;google.github.io/adk-docs/evaluate&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Google Cloud Trace &amp;amp; OpenTelemetry for Python:&lt;/strong&gt; &lt;a href="https://cloud.google.com/trace/docs/setup/python-ot" rel="noopener noreferrer"&gt;cloud.google.com/trace/docs/setup/python-ot&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gemma Chat &amp;amp; Function Calling Formatting (&lt;code&gt;&amp;lt;start_of_turn&amp;gt;&lt;/code&gt;):&lt;/strong&gt; &lt;a href="https://ai.google.dev/gemma/docs/formatting" rel="noopener noreferrer"&gt;ai.google.dev/gemma/docs/formatting&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>googleai</category>
      <category>python</category>
      <category>gemma</category>
      <category>googlecloud</category>
    </item>
    <item>
      <title>Architecting Autonomous Lakehouse Agents: Governed Iceberg Analytics with Gemini 2.5 Flash and BigLake</title>
      <dc:creator>Robina Mirbahar</dc:creator>
      <pubDate>Thu, 15 Oct 2026 15:57:55 +0000</pubDate>
      <link>https://dev.to/gde/architecting-autonomous-lakehouse-agents-governed-iceberg-analytics-with-gemini-25-flash-and-4ai9</link>
      <guid>https://dev.to/gde/architecting-autonomous-lakehouse-agents-governed-iceberg-analytics-with-gemini-25-flash-and-4ai9</guid>
      <description>&lt;p&gt;The decoupling of compute from storage has positioned &lt;strong&gt;Apache Iceberg&lt;/strong&gt; as the de facto open table format across enterprise cloud data architectures. By providing ACID transactions, schema evolution without rewriting data files, hidden partitioning, and time-travel snapshots, Iceberg enables organizations to store petabytes of analytical data in &lt;strong&gt;Google Cloud Storage (GCS)&lt;/strong&gt; while querying it via heterogeneous engines.&lt;/p&gt;

&lt;p&gt;However, bridging autonomous Large Language Model (LLM) agents with production Iceberg lakehouses creates severe architectural challenges:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Financial Denial-of-Service (FDOS) &amp;amp; Runaway Queries:&lt;/strong&gt; In a lakehouse with 50+ TB tables, an unconstrained LLM generating an unpartitioned &lt;code&gt;SELECT *&lt;/code&gt; or multi-way cross-join will trigger multi-hundred-dollar scanning fees in seconds.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dynamic Schema Drift &amp;amp; Partition Transform Hallucinations:&lt;/strong&gt; Apache Iceberg separates logical table schemas from physical partition specs (&lt;code&gt;identity&lt;/code&gt;, &lt;code&gt;year&lt;/code&gt;, &lt;code&gt;month&lt;/code&gt;, &lt;code&gt;bucket[N]&lt;/code&gt;, &lt;code&gt;truncate[W]&lt;/code&gt;). Traditional static prompt engineering inevitably causes models to hallucinate non-existent partition columns or miss partition pruning entirely.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Destructive Mutation Risks:&lt;/strong&gt; Semantic misinterpretations can cause models to emit non-idempotent or destructive DDL/DML statements (&lt;code&gt;DROP&lt;/code&gt;, &lt;code&gt;DELETE&lt;/code&gt;, &lt;code&gt;TRUNCATE&lt;/code&gt;, &lt;code&gt;ALTER&lt;/code&gt;).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To solve these problems, I architected and built an end-to-end, production-grade &lt;strong&gt;Autonomous Data Agent&lt;/strong&gt; using &lt;strong&gt;Google’s Agent Development Kit (ADK)&lt;/strong&gt; design patterns, &lt;strong&gt;Gemini 2.5 Flash&lt;/strong&gt;, &lt;strong&gt;BigLake Iceberg REST Catalogs&lt;/strong&gt;, and &lt;strong&gt;Abstract Syntax Tree (AST) guardrails&lt;/strong&gt;. In this article, I will walk you through how I designed and implemented this system.&lt;/p&gt;




&lt;h2&gt;
  
  
  🏛️ System Architecture Topology
&lt;/h2&gt;

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

&lt;p&gt;In my architecture, the agent never directly touches physical data files or executes raw, unvetted SQL against storage engines. Instead, I designed it to operate inside a &lt;strong&gt;closed-loop, deterministic execution framework&lt;/strong&gt; structured across three distinct tiers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                            User Natural Language Query
                                       │
                                       ▼
                     ┌───────────────────────────────────┐
                     │    Gemini 2.5 Flash Orchestrator   │
                     │  (Temperature: 0.0, Seed-Locked)  │
                     └─────────────────┬─────────────────┘
                                       │
                ┌──────────────────────┴──────────────────────┐
                │                                             │
                ▼                                             ▼
    ┌──────────────────────┐                     ┌─────────────────────────┐
    │ Tier 1: Discovery    │                     │ Tier 2: Validation      │
    │ Iceberg REST Catalog │                     │ AST Read-Only Check     │
    │ Partition Layouts    │                     │ BigQuery Zero-Cost Dry  │
    │ Active Snapshots     │                     │ Scan Budget Gate (&amp;lt;500M)│
    └──────────┬───────────┘                     └────────────┬────────────┘
               │                                              │
               │ [Validated AST + Estimated Cost Passed]     │
               └──────────────────────┬───────────────────────┘
                                      │
                                      ▼
                        ┌───────────────────────────┐
                        │ Tier 3: Vectorized Engine │
                        │ BigQuery Native Vectorized│
                        │ Parquet Pushdown via GCS  │
                        └─────────────┬─────────────┘
                                      │
                                      ▼
                        Bounded Result Dataframe
                                      │
                                      ▼
                      Synthesized Analytical Response
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Three Operational Tiers:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Tier 1: Deep Lakehouse Metadata &amp;amp; Partition Probing:&lt;/strong&gt; The agent inspects the BigLake Iceberg REST Catalog at runtime to dynamically inspect the active schema, column types, clustering keys, and physical partition transforms.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tier 2: Static AST Analysis &amp;amp; Zero-Cost Dry-Run Guardrails:&lt;/strong&gt; The generated SQL undergoes Abstract Syntax Tree (AST) token parsing via SQLGlot to ensure read-only immutability. It is then compiled through BigQuery’s zero-cost dry-run API to enforce an absolute byte scanning budget (&amp;lt;500 MB).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tier 3: Governed Vectorized Read Execution:&lt;/strong&gt; The approved query is executed using BigLake's vectorized Parquet reader directly over Cloud Storage, returning a strictly bounded result payload.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  📦 Environment Setup &amp;amp; Dependencies
&lt;/h2&gt;

&lt;p&gt;Ensure your execution environment has the required Google Cloud and parsing dependencies installed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;google-genai google-cloud-bigquery sqlglot pydantic
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;typing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Dict&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;List&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Optional&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;pydantic&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;BaseModel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Field&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;sqlglot&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;sqlglot&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;exp&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;google&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;genai&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;google.genai&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;types&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;google.cloud&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;bigquery&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;google.cloud.exceptions&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;GoogleCloudError&lt;/span&gt;

&lt;span class="c1"&gt;# Configuration &amp;amp; Runtime Limits
&lt;/span&gt;&lt;span class="n"&gt;PROJECT_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;GCP_PROJECT_ID&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;enterprise-lakehouse-prod&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;LOCATION&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;GCP_REGION&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;us-central1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;MAX_SCAN_LIMIT_BYTES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt;  &lt;span class="c1"&gt;# Strict 500 MB Safety Ceiling
&lt;/span&gt;
&lt;span class="c1"&gt;# Initialize Clients
&lt;/span&gt;&lt;span class="n"&gt;bq_client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bigquery&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;project&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;PROJECT_ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;location&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;LOCATION&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;ai_client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;genai&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;api_key&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;GEMINI_API_KEY&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;h2&gt;
  
  
  🔧 Tier 1: Iceberg REST Catalog &amp;amp; Metadata Discovery Tool
&lt;/h2&gt;

&lt;p&gt;Passing static schemas inside system prompts fails because modern Iceberg tables continuously evolve. To solve this, I built a metadata discovery tool that allows my agent to inspect table schemas, field constraints, partitioning strategies, and clustering keys dynamically at runtime:&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;ColumnDefinition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BaseModel&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="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;data_type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Optional&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="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TableMetadataResponse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BaseModel&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;table_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;table_type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;columns&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ColumnDefinition&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;partition_specs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&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="n"&gt;clustering_keys&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&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="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_lakehouse_table_schema&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dataset_id&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;table_id&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;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
    Queries the BigLake Iceberg REST Catalog to extract dynamic table schema,
    column types, partition transformations, and clustering configurations.
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;full_table_path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;PROJECT_ID&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;.&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;dataset_id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;.&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;table_id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;table&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bq_client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_table&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;full_table_path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;GoogleCloudError&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&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;ERROR: Failed to resolve table &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;full_table_path&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

    &lt;span class="n"&gt;columns&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;field&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;table&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;columns&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="nc"&gt;ColumnDefinition&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="n"&gt;field&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;data_type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;field&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;field_type&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="n"&gt;field&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mode&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="n"&gt;field&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;description&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;No description provided&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;partition_specs&lt;/span&gt; &lt;span class="o"&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;table&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;time_partitioning&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;partition_specs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&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;Time Partition Field: &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;table&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;time_partitioning&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;field&lt;/span&gt;&lt;span class="si"&gt;}&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="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;(Type: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;table&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;time_partitioning&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;type_&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;)&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="n"&gt;table&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;range_partitioning&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;partition_specs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&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;Range Partition Field: &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;table&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;range_partitioning&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;field&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="n"&gt;clustering_keys&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;table&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;clustering_fields&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;table&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;clustering_fields&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;

    &lt;span class="n"&gt;metadata&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;TableMetadataResponse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;table_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;full_table_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;table_type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;table&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;table_type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;columns&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;columns&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;partition_specs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;partition_specs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;clustering_keys&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;clustering_keys&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;model_dump_json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;indent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🛡️ Tier 2: AST Read-Only Validation &amp;amp; BigQuery Dry-Run Guardrails
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F88t685fci169wwvrf7dw.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F88t685fci169wwvrf7dw.jpg" alt="The 500MB Safety Gate: Catching Disasters in Real-Time!" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To prevent accidental multi-terabyte full-table scans, I implemented a validation gate that runs two sequential read-only and cost layers before any query can touch the lakehouse:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;AST Token Traversal:&lt;/strong&gt; Disallows all non-SELECT queries, subquery mutations, and administrative commands using &lt;code&gt;sqlglot&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Zero-Cost Dry Run:&lt;/strong&gt; Pre-compiles the query on Google Cloud to calculate the exact &lt;code&gt;total_bytes_processed&lt;/code&gt; before billing occurs.
&lt;/li&gt;
&lt;/ol&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;audit_and_estimate_sql_cost&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sql_statement&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;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
    Performs Abstract Syntax Tree (AST) validation and a zero-cost BigQuery dry-run.
    Enforces a strict 500MB scan ceiling and blocks all non-SELECT DDL/DML statements.
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="c1"&gt;# -------------------------------------------------------------
&lt;/span&gt;    &lt;span class="c1"&gt;# Layer 1: Abstract Syntax Tree (AST) Immutability Check
&lt;/span&gt;    &lt;span class="c1"&gt;# -------------------------------------------------------------
&lt;/span&gt;    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;parsed_tree&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sqlglot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse_one&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sql_statement&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;bigquery&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;parse_err&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status&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;REJECTED&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;reason&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;SQL Syntax/Parsing Error: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;parse_err&lt;/span&gt;&lt;span class="p"&gt;)&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="c1"&gt;# Ensure the root expression is strictly a SELECT or UNION
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="nf"&gt;isinstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;parsed_tree&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;exp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Select&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;exp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Union&lt;/span&gt;&lt;span class="p"&gt;)):&lt;/span&gt;
        &lt;span class="k"&gt;return&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status&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;REJECTED&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;reason&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;Root statement must be a read-only SELECT or UNION query.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="c1"&gt;# Disallow destructive or mutating expressions anywhere in the AST
&lt;/span&gt;    &lt;span class="n"&gt;forbidden_ast_nodes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;exp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Drop&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;exp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Delete&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;exp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TruncateTable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;exp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Insert&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;exp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Update&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;exp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AlterTable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;exp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Command&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;exp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Merge&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;parsed_tree&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;walk&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;isinstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;forbidden_ast_nodes&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="k"&gt;return&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status&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;REJECTED&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;reason&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;Forbidden mutation expression detected: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;upper&lt;/span&gt;&lt;span class="p"&gt;()&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="c1"&gt;# -------------------------------------------------------------
&lt;/span&gt;    &lt;span class="c1"&gt;# Layer 2: BigQuery Dry-Run Scan Evaluation (Zero-Cost Metric)
&lt;/span&gt;    &lt;span class="c1"&gt;# -------------------------------------------------------------
&lt;/span&gt;    &lt;span class="n"&gt;job_config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bigquery&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;QueryJobConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;dry_run&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;use_query_cache&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="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;dry_run_job&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bq_client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sql_statement&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;job_config&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;job_config&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;scanned_bytes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dry_run_job&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;total_bytes_processed&lt;/span&gt;
        &lt;span class="n"&gt;scanned_mb&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;scanned_bytes&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1024&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;2&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;scanned_bytes&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;MAX_SCAN_LIMIT_BYTES&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;limit_mb&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MAX_SCAN_LIMIT_BYTES&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1024&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;return&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status&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;REJECTED&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;scanned_mb&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;scanned_mb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;limit_mb&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;limit_mb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;reason&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="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Query scan budget exceeded: Proposed query scans &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;scanned_mb&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; MB, &lt;/span&gt;&lt;span class="sh"&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;which violates the &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;limit_mb&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; MB safety limit. &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
                    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Action Required: Prune partitions by narrowing date/timestamp or cluster filters.&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="k"&gt;return&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status&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;APPROVED&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;scanned_bytes&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;scanned_bytes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;scanned_mb&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;scanned_mb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;message&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;Cost budget check passed. Query is safe to execute.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;GoogleCloudError&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;gcp_err&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status&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;REJECTED&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;reason&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;BigQuery Compilation Failure: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gcp_err&lt;/span&gt;&lt;span class="p"&gt;)&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  ⚡ Tier 3: Governed Vectorized Read Execution
&lt;/h2&gt;

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

&lt;p&gt;Once Tier 2 returns &lt;code&gt;APPROVED&lt;/code&gt;, I dispatch the query through BigLake's vectorized query engine over Apache Iceberg Parquet files, enforcing a job-level billing cap as defense-in-depth:&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;execute_lakehouse_query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sql_statement&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;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
    Executes a vetted, read-only analytical query against Apache Iceberg via BigLake.
    Returns the tabular result set capped to 50 rows to prevent memory saturation.
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="c1"&gt;# Enforce maximum billing ceiling at the job level as defense-in-depth
&lt;/span&gt;    &lt;span class="n"&gt;job_config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bigquery&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;QueryJobConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;maximum_bytes_billed&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;MAX_SCAN_LIMIT_BYTES&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;query_job&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bq_client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sql_statement&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;job_config&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;job_config&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;query_job&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;result&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max_results&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;rows&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;results&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;rows&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status&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;SUCCESS&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;message&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 executed successfully. Result set is empty.&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;data&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="k"&gt;return&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status&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;SUCCESS&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;row_count&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;data&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&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;except&lt;/span&gt; &lt;span class="n"&gt;GoogleCloudError&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status&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;EXECUTION_ERROR&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;error&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🤖 Orchestration Loop with Gemini 2.5 Flash
&lt;/h2&gt;

&lt;p&gt;Next, I instantiate &lt;strong&gt;Gemini 2.5 Flash&lt;/strong&gt; using the official &lt;code&gt;google-genai&lt;/code&gt; SDK, binding my three deterministic tools and establishing an immutable verification protocol:&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;SYSTEM_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 an Autonomous Data Lakehouse Agent governing Apache Iceberg tables on Google Cloud.
You interact with production analytics systems through a strict three-tier verification lifecycle.

MANDATORY PROTOCOL:
1. DISCOVERY: ALWAYS call `get_lakehouse_table_schema` before authoring any SQL. Never guess column names or partition schemes.
2. SYNTHESIS: Write standard GoogleSQL optimized for Iceberg partition pruning.
3. VALIDATION: Pass your candidate SQL to `audit_and_estimate_sql_cost`.
4. SELF-CORRECTION: If status is &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;REJECTED&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;:
   - Analyze the reason carefully.
   - If rejected due to scan limits, add tighter partition bounds (e.g. narrow timestamp filters).
   - Re-submit to `audit_and_estimate_sql_cost`.
5. EXECUTION: ONLY call `execute_lakehouse_query` after receiving an explicit &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;APPROVED&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt; status.
6. INSIGHT: Provide structured, executive-level answers with key metrics highlighted.
&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;create_autonomous_lakehouse_agent&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;ai_client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chats&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gemini-2.5-flash&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;config&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;GenerateContentConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;system_instruction&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;SYSTEM_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_lakehouse_table_schema&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;audit_and_estimate_sql_cost&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;execute_lakehouse_query&lt;/span&gt;
            &lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="n"&gt;temperature&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;  &lt;span class="c1"&gt;# Zero temperature for deterministic architectural accuracy
&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;h2&gt;
  
  
  🧪 Trace Walkthrough: Autonomous Recovery from Budget Violations
&lt;/h2&gt;

&lt;p&gt;Here is a real execution trace from my test environment showing how the agent autonomously diagnoses and recovers from an excessive partition scan:&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;if&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;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;agent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;create_autonomous_lakehouse_agent&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;prompt&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;In the dataset &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;iot_telemetry&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;, inspect table &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;fleet_sensors&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Identify the top 5 vehicles reporting anomalous thermal warnings.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send_message&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;=== FINAL AGENT SYNTHESIS ===&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Complete Execution Trace:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[STEP 1: METADATA PROBING]
--&amp;gt; Call: get_lakehouse_table_schema(dataset_id="iot_telemetry", table_id="fleet_sensors")
&amp;lt;-- Response: {
  "table_id": "enterprise-lakehouse-prod.iot_telemetry.fleet_sensors",
  "table_type": "EXTERNAL",
  "columns": [
    {"name": "vehicle_id", "data_type": "STRING", "mode": "REQUIRED"},
    {"name": "recorded_at", "data_type": "TIMESTAMP", "mode": "REQUIRED"},
    {"name": "engine_temp_c", "data_type": "FLOAT", "mode": "NULLABLE"},
    {"name": "anomaly_flag", "data_type": "BOOLEAN", "mode": "NULLABLE"}
  ],
  "partition_specs": ["Time Partition Field: 'recorded_at' (Type: DAY)"],
  "clustering_keys": ["vehicle_id"]
}

[STEP 2: NAIVE QUERY FORMULATION &amp;amp; AUDIT]
--&amp;gt; Call: audit_and_estimate_sql_cost(
  sql_statement="SELECT vehicle_id, COUNT(*) as anomalies FROM `enterprise-lakehouse-prod.iot_telemetry.fleet_sensors` WHERE anomaly_flag = TRUE GROUP BY 1 ORDER BY anomalies DESC LIMIT 5"
)
&amp;lt;-- Response: {
  "status": "REJECTED",
  "scanned_mb": 1845.20,
  "limit_mb": 500.0,
  "reason": "Query scan budget exceeded: Proposed query scans 1845.2 MB, which violates the 500.0 MB safety limit. Action Required: Prune partitions by narrowing date/timestamp or cluster filters."
}

[STEP 3: AUTONOMOUS PARTITION PRUNING &amp;amp; RE-AUDIT]
--&amp;gt; Agent Step Reasoning: The query scanned the entire historical Iceberg dataset (1.84 GB). I must restrict the `recorded_at` partition column to a recent time boundary.
--&amp;gt; Call: audit_and_estimate_sql_cost(
  sql_statement="SELECT vehicle_id, COUNT(*) as anomalies FROM `enterprise-lakehouse-prod.iot_telemetry.fleet_sensors` WHERE anomaly_flag = TRUE AND recorded_at &amp;gt;= TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 14 DAY) GROUP BY 1 ORDER BY anomalies DESC LIMIT 5"
)
&amp;lt;-- Response: {
  "status": "APPROVED",
  "scanned_bytes": 68157440,
  "scanned_mb": 65.0,
  "message": "Cost budget check passed. Query is safe to execute."
}

[STEP 4: EXECUTION]
--&amp;gt; Call: execute_lakehouse_query(...)
&amp;lt;-- Response: {
  "status": "SUCCESS",
  "row_count": 5,
  "data": [
    {"vehicle_id": "VH-882", "anomalies": 312},
    {"vehicle_id": "VH-104", "anomalies": 245},
    {"vehicle_id": "VH-902", "anomalies": 189},
    {"vehicle_id": "VH-311", "anomalies": 154},
    {"vehicle_id": "VH-529", "anomalies": 98}
  ]
}

[FINAL AGENT SYNTHESIS]
Based on analysis of the fleet sensors dataset over the past 14 days (scanning 65.0 MB), the top 5 vehicles experiencing anomalous thermal events are:
1. **VH-882**: 312 warnings
2. **VH-104**: 245 warnings
3. **VH-902**: 189 warnings
4. **VH-311**: 154 warnings
5. **VH-529**: 98 warnings
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  📊 Architectural Evaluation: Direct LLM vs. Governed Lakehouse Agent
&lt;/h2&gt;

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

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Operational Dimension&lt;/th&gt;
&lt;th&gt;Ungoverned Direct LLM Text-to-SQL&lt;/th&gt;
&lt;th&gt;Autonomous Governed Lakehouse Agent&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Financial Exposure&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Unbounded risk of multi-terabyte scans&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Deterministic byte budget gate (&amp;lt;500 MB)&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Partition Awareness&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Hallucinates static date strings&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Dynamic Iceberg REST catalog probing&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;AST Validation&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Susceptible to destructive mutations&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Strict token validation via SQLGlot AST&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Compute Topology&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Requires duplicate data marts / pipelines&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Direct BigLake vectorized scans over GCS&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Error Handling&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Fatal query crash terminates turn&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Autonomous self-correcting partition refinement&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  🎯 Production Engineering Takeaways
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Deterministic Guardrails Outweigh Prompt Engineering:&lt;/strong&gt; System instructions alone are insufficient to guarantee financial or operational safety. Programmatic gates (AST parsing + zero-cost dry runs) provide mathematically verified boundaries.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Treat Iceberg Catalogs as Live Agent Memory:&lt;/strong&gt; Inspecting metadata directly from the catalog removes schema drift and prevents hallucinated column structures.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Leverage BigQuery Zero-Cost Dry Runs:&lt;/strong&gt; Using BigQuery's free compilation and byte estimation API creates an ideal reward signal for agent self-correction.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  🔗 Official Documentation &amp;amp; Technical References
&lt;/h2&gt;

&lt;p&gt;To implement or extend this architecture, refer to the verified technical documentation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Google BigLake &amp;amp; Iceberg Integration:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://cloud.google.com/bigquery/docs/biglake-intro" rel="noopener noreferrer"&gt;Google Cloud BigLake Overview &amp;amp; Iceberg Tables&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://cloud.google.com/bigquery/docs/iceberg-tables" rel="noopener noreferrer"&gt;Creating and Querying Iceberg Tables in BigLake&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://cloud.google.com/bigquery/docs/dry-run-queries" rel="noopener noreferrer"&gt;BigQuery Dry-Run Estimation &amp;amp; Cost Optimization&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Google Gemini &amp;amp; GenAI SDK:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://cloud.google.com/vertex-ai/docs/generative-ai/model-reference/gemini" rel="noopener noreferrer"&gt;Google GenAI SDK Documentation (google-genai)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://cloud.google.com/vertex-ai/docs/generative-ai/multimodal/function-calling" rel="noopener noreferrer"&gt;Function Calling &amp;amp; Tool Use with Gemini 2.5 Flash&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Apache Iceberg &amp;amp; Open Table Architecture:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://iceberg.apache.org/spec/" rel="noopener noreferrer"&gt;Apache Iceberg Table Specification &amp;amp; Partition Evolution&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://iceberg.apache.org/concepts/catalog/" rel="noopener noreferrer"&gt;Apache Iceberg REST Catalog Specification&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SQL Abstract Syntax Tree (AST) Parsing:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://sqlglot.com/" rel="noopener noreferrer"&gt;SQLGlot Transpiler &amp;amp; AST Parser Documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>googleai</category>
      <category>python</category>
      <category>bigquery</category>
      <category>googlecloud</category>
    </item>
    <item>
      <title>FreelanceShield AI: Local Open-Weight Gemma Scope Creep Detector &amp; TabPFN Invoice Risk Forecaster</title>
      <dc:creator>Robina Mirbahar</dc:creator>
      <pubDate>Tue, 13 Oct 2026 21:14:49 +0000</pubDate>
      <link>https://dev.to/robinamirbahar/freelanceshield-ai-local-open-weight-scope-creep-detector-tabpfn-invoice-risk-forecaster-83k</link>
      <guid>https://dev.to/robinamirbahar/freelanceshield-ai-local-open-weight-scope-creep-detector-tabpfn-invoice-risk-forecaster-83k</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/hacktoberfest-week2-2026-10-12"&gt;Hacktoberfest Open-Source AI Challenge Week 2: Side Hustle&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;Independent developers, designers, and boutique agencies lose an average of &lt;strong&gt;22% of their annual income&lt;/strong&gt; to two silent side-hustle killers:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Unbilled Scope Creep ("Quick Favors")&lt;/strong&gt;: &lt;em&gt;"Hey! Can we quickly add a React Native mobile wrapper, dark mode across 14 charts, and an Okta SAML webhook before Friday's launch?"&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Chronic Late-Paying Invoices&lt;/strong&gt;: Accepting net-30/net-45 terms or zero-deposit expansions from high-risk clients without data-driven payment risk visibility.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Why haven't cloud AI wrappers solved this? &lt;strong&gt;Because solo freelancers need zero-cost, offline predictability.&lt;/strong&gt; Uploading hundreds of pages of Statements of Work (SOWs) and historical client billing ledgers to metered cloud APIs adds recurring monthly token bills.&lt;/p&gt;

&lt;p&gt;So I built &lt;strong&gt;🛡️ FreelanceShield AI&lt;/strong&gt; - a &lt;strong&gt;100% Local-First Open-Weight Google &lt;code&gt;Gemma&lt;/code&gt; Scope Creep Detector, 1-Click Change Order Generator &amp;amp; Prior Labs &lt;code&gt;TabPFN&lt;/code&gt; Invoice Risk Forecaster&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%2Fgb402o2btpz42afs0wij.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgb402o2btpz42afs0wij.jpg" alt="FreelanceShield AI Architecture Banner" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Who Would Pay For It?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Solo Freelancers &amp;amp; Side Hustlers ($19/mo Pro Desktop/Local License):&lt;/strong&gt; Recovers an average of &lt;strong&gt;$1,420/month&lt;/strong&gt; in unbilled hours on the very first caught scope expansion - delivering a &lt;strong&gt;74x ROI&lt;/strong&gt; with &lt;strong&gt;$0.00/month&lt;/strong&gt; in cloud API token costs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Boutique Dev &amp;amp; Design Agencies ($79/mo Self-Hosted Team Container on Render):&lt;/strong&gt; Gives account managers an instant, polite, clause-grounded Change Order PDF generator + tabular cashflow risk radar across all active retainers.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;🚀 &lt;strong&gt;Live Interactive Web App (Try 4 Real Freelancer Scenarios + Live Local Gemma / Ollama Connector + TabPFN Forecaster in Your Browser):&lt;/strong&gt;
👉 &lt;strong&gt;&lt;a href="https://robinamirbahar.github.io/freelanceshield-open-ai-side-hustle/" rel="noopener noreferrer"&gt;https://robinamirbahar.github.io/freelanceshield-open-ai-side-hustle/&lt;/a&gt;&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  What You Can Test Live Right Now:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Switch Between 4 Real-World Freelancer Scope Creep Scenarios&lt;/strong&gt; (or type your own custom SOW clauses &amp;amp; sneaky client Slack message):

&lt;ul&gt;
&lt;li&gt;📱 &lt;em&gt;"Quick Dark Mode + React Native App"&lt;/em&gt; (&lt;code&gt;+$3,625 / 29 unbilled hrs caught&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;🤖 &lt;em&gt;"Just Add Multi-Tenant SSO &amp;amp; SOC2 Questionnaire"&lt;/em&gt; (&lt;code&gt;+$4,500 / 30 unbilled hrs caught&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;🎨 &lt;em&gt;"5 Extra Competitor Landing Pages + 3D ProductHunt Video"&lt;/em&gt; (&lt;code&gt;+$3,850 / 35 unbilled hrs caught&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;✅ &lt;em&gt;Legitimate In-Scope Safari Bug Fix&lt;/em&gt; (&lt;code&gt;$0 - Verified covered under Clause 1 &amp;amp; Revision Round 1&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;1-Click Polite Counter-Proposal &amp;amp; Printable Change Order PDF (&lt;code&gt;#CO-2026-089&lt;/code&gt;)&lt;/strong&gt;: Generates a warm, relationship-preserving reply with itemized hours, clause citations, and a printable Change Order PDF addendum powered by &lt;strong&gt;Google's open-weight &lt;code&gt;Gemma&lt;/code&gt; model&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Interactive Prior Labs &lt;code&gt;TabPFN&lt;/code&gt; Invoice Late-Payment Risk &amp;amp; Q4 Cashflow Chart&lt;/strong&gt;: Simulate new invoices, switch client tiers (&lt;code&gt;Seed Startup&lt;/code&gt;, &lt;code&gt;Enterprise Net-45&lt;/code&gt;, &lt;code&gt;Repeat VIP&lt;/code&gt;, &lt;code&gt;Unverified Client&lt;/code&gt;), and watch the zero-shot tabular risk classifier adjust the recommended upfront deposit (&lt;code&gt;50%&lt;/code&gt; vs &lt;code&gt;100% Escrow&lt;/code&gt;).&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Code
&lt;/h2&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/RobinaMirbahar" rel="noopener noreferrer"&gt;
        RobinaMirbahar
      &lt;/a&gt; / &lt;a href="https://github.com/RobinaMirbahar/freelanceshield-open-ai-side-hustle" rel="noopener noreferrer"&gt;
        freelanceshield-open-ai-side-hustle
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      FreelanceShield AI — Local Open-Weight Scope Creep Detector, 1-Click Change Order Generator &amp;amp; TabPFN Invoice Risk Forecaster — by Robina Mirbahar
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;🛡️ FreelanceShield AI — Local Open-Weight Scope Creep Detector &amp;amp; TabPFN-3.5 Invoice Forecaster&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/332429d509684bc378b0c42e2ab6eba377fd8ee7896ebbfd90fbf57f9487d7fe/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c6f63616c5f41492d4f70656e5f576569676874735f47656d6d612d3432383546343f7374796c653d666f722d7468652d6261646765266c6f676f3d676f6f676c65266c6f676f436f6c6f723d7768697465"&gt;&lt;img src="https://camo.githubusercontent.com/332429d509684bc378b0c42e2ab6eba377fd8ee7896ebbfd90fbf57f9487d7fe/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c6f63616c5f41492d4f70656e5f576569676874735f47656d6d612d3432383546343f7374796c653d666f722d7468652d6261646765266c6f676f3d676f6f676c65266c6f676f436f6c6f723d7768697465" alt="Local_AI"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/b750a5213141f3bf77af735bbbed3f6241c15bf0919842655d37ca331fc3f2ae/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f546162756c61725f4d4c2d54616250464e5f5269736b5f466f72656361737465722d3046394435383f7374796c653d666f722d7468652d6261646765266c6f676f3d707974686f6e266c6f676f436f6c6f723d7768697465"&gt;&lt;img src="https://camo.githubusercontent.com/b750a5213141f3bf77af735bbbed3f6241c15bf0919842655d37ca331fc3f2ae/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f546162756c61725f4d4c2d54616250464e5f5269736b5f466f72656361737465722d3046394435383f7374796c653d666f722d7468652d6261646765266c6f676f3d707974686f6e266c6f676f436f6c6f723d7768697465" alt="Tabular_ML"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/b58f218e35b7e316ce9a88eab390fce219640e2c9276ff57ac7821f29c67aeb1/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f507269766163792d313030255f4c6f63616c5f436f6e7472616374732d3743334145443f7374796c653d666f722d7468652d6261646765266c6f676f3d7365637572697479266c6f676f436f6c6f723d7768697465"&gt;&lt;img src="https://camo.githubusercontent.com/b58f218e35b7e316ce9a88eab390fce219640e2c9276ff57ac7821f29c67aeb1/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f507269766163792d313030255f4c6f63616c5f436f6e7472616374732d3743334145443f7374796c653d666f722d7468652d6261646765266c6f676f3d7365637572697479266c6f676f436f6c6f723d7768697465" alt="Privacy"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/66ab7903512936a3c10e3b75e09749f6a841bced8799af408706383b02c86398/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f417574686f722d526f62696e615f4d697262616861722d3138313731373f7374796c653d666f722d7468652d6261646765266c6f676f3d676974687562266c6f676f436f6c6f723d7768697465"&gt;&lt;img src="https://camo.githubusercontent.com/66ab7903512936a3c10e3b75e09749f6a841bced8799af408706383b02c86398/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f417574686f722d526f62696e615f4d697262616861722d3138313731373f7374796c653d666f722d7468652d6261646765266c6f676f3d676974687562266c6f676f436f6c6f723d7768697465" alt="Author"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Author &amp;amp; Architect:&lt;/strong&gt; &lt;a href="https://github.com/RobinaMirbahar" rel="noopener noreferrer"&gt;Robina Mirbahar&lt;/a&gt; (Google Developer Expert in Cloud &amp;amp; AI)&lt;br&gt;
&lt;strong&gt;Focus:&lt;/strong&gt; Local Open-Weight Scope Creep Detector, 1-Click Change Order Generator &amp;amp; TabPFN Invoice Risk Forecaster&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;🎯 Why I Built FreelanceShield AI (Engineering Purpose &amp;amp; Real-World Value)&lt;/h2&gt;
&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;1. 🛡️ Protecting Independent Engineers from Unpaid Scope Creep&lt;/h3&gt;
&lt;/div&gt;
&lt;p&gt;Freelancers and boutique consultancies lose thousands of dollars when casual client messages quietly expand deliverables beyond the signed Statement of Work (SOW). I built FreelanceShield AI to compare incoming client requests against baseline SOW clauses automatically.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;2. 📊 Hybrid AI: Open-Weights LLM + TabPFN Tabular Risk Forecasting&lt;/h3&gt;

&lt;/div&gt;
&lt;p&gt;I combined local open-weights Gemma (for semantic contract diffing and 1-click Change Order drafting) with TabPFN foundation-model tabular inference to predict invoice late-payment probability.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;3. 🔒 100% Local NDA-Safe Execution&lt;/h3&gt;

&lt;/div&gt;
&lt;p&gt;Client contracts and pricing terms never leave your machine, ensuring strict NDA compliance.&lt;/p&gt;…&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/RobinaMirbahar/freelanceshield-open-ai-side-hustle" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;





&lt;h2&gt;
  
  
  How I Built It
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;FreelanceShield AI&lt;/strong&gt; combines &lt;strong&gt;two distinct paradigms of open-source AI&lt;/strong&gt; - &lt;strong&gt;Google's open-weight &lt;code&gt;Gemma&lt;/code&gt; model&lt;/strong&gt; for unstructured contract &amp;amp; Slack semantic auditing, and &lt;strong&gt;Prior Labs' &lt;code&gt;TabPFN&lt;/code&gt;&lt;/strong&gt; tabular foundation model for small-table financial risk forecasting:&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%2Fr8aepuxyu681h8v55xya.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fr8aepuxyu681h8v55xya.jpg" alt="FreelanceShield AI: 100% Local Offline-First Architecture" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Local Open-Weight Contract Auditing &amp;amp; Polite Change-Order Drafting with &lt;strong&gt;Google &lt;code&gt;Gemma&lt;/code&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;In &lt;a href="https://github.com/RobinaMirbahar/freelanceshield-open-ai-side-hustle/blob/main/agent_backend.py" rel="noopener noreferrer"&gt;&lt;code&gt;agent_backend.py&lt;/code&gt;&lt;/a&gt; and &lt;a href="https://github.com/RobinaMirbahar/freelanceshield-open-ai-side-hustle/blob/main/app.js" rel="noopener noreferrer"&gt;&lt;code&gt;app.js&lt;/code&gt;&lt;/a&gt;, I built the contract auditing engine around &lt;strong&gt;Google's open-weight &lt;code&gt;Gemma&lt;/code&gt; family (&lt;code&gt;gemma4:e4b&lt;/code&gt; / &lt;code&gt;gemma3:12b&lt;/code&gt; via Ollama)&lt;/strong&gt; so freelancers can compare signed SOW clauses against incoming client Slack/email messages 100% offline on their laptop with zero cloud API latency or token costs:&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;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;numpy&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;tabpfn&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;TabPFNClassifier&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;predict_late_payment_with_tabpfn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;invoice_usd&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;net_terms_days&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;prior_late_count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;has_scope_creep&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;deposit_pct&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;,&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="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
    Runs Prior Labs TabPFN-3.5 zero-shot tabular classification on the freelancer&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;s
    historical invoice CSV ledger inside the wider FreelanceShield prediction agent
    to forecast &amp;gt;14-day payment delay probability and prescribe escrow terms.
    Supports both Prior Labs Cloud API (platform.priorlabs.ai / TabPFN-3.5) and local inference.
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;X_train&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;HISTORICAL_INVOICES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;drop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;columns&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;delayed_over_14d&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]).&lt;/span&gt;&lt;span class="n"&gt;values&lt;/span&gt;
    &lt;span class="n"&gt;y_train&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;HISTORICAL_INVOICES&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;delayed_over_14d&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;values&lt;/span&gt;
    &lt;span class="n"&gt;X_query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;array&lt;/span&gt;&lt;span class="p"&gt;([[&lt;/span&gt;
        &lt;span class="n"&gt;invoice_usd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;net_terms_days&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;prior_late_count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;has_scope_creep&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;deposit_pct&lt;/span&gt;
    &lt;span class="p"&gt;]])&lt;/span&gt;

    &lt;span class="n"&gt;clf&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;TabPFNClassifier&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;device&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cpu&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;clf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;X_train&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y_train&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;prob&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;clf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;predict_proba&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;X_query&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="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="n"&gt;risk_pct&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prob&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;100.0&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;recommended_deposit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;risk_pct&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mf"&gt;75.0&lt;/span&gt; &lt;span class="nf"&gt;else &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;risk_pct&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mf"&gt;40.0&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="mi"&gt;25&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;model&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;Prior Labs TabPFN-3.5&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;late_payment_probability_pct&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;risk_pct&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;recommended_escrow_deposit_pct&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;recommended_deposit&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;
  
  
  2. Zero-Shot Small-Table Invoice Risk Prediction with &lt;strong&gt;Prior Labs &lt;code&gt;TabPFN-3.5&lt;/code&gt;&lt;/strong&gt; (Embedded in the Prediction Agent Loop)
&lt;/h3&gt;

&lt;p&gt;A solo freelancer doesn't have 100,000 rows of invoice history to train a deep neural network or tune an XGBoost pipeline - they typically have &lt;strong&gt;10 to 50 past invoices&lt;/strong&gt; in a CSV ledger (&lt;code&gt;invoice_usd&lt;/code&gt;, &lt;code&gt;net_terms_days&lt;/code&gt;, &lt;code&gt;prior_late_count&lt;/code&gt;, &lt;code&gt;has_scope_creep&lt;/code&gt;, &lt;code&gt;deposit_pct&lt;/code&gt;, &lt;code&gt;delayed_over_14d&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;This small-table regime is where &lt;strong&gt;Prior Labs' &lt;code&gt;TabPFN-3.5&lt;/code&gt;&lt;/strong&gt; (&lt;code&gt;platform.priorlabs.ai&lt;/code&gt; / &lt;code&gt;tabpfn&lt;/code&gt;) shines! Inside &lt;a href="https://github.com/RobinaMirbahar/freelanceshield-open-ai-side-hustle/blob/main/agent_backend.py" rel="noopener noreferrer"&gt;&lt;code&gt;agent_backend.py&lt;/code&gt;&lt;/a&gt;, &lt;code&gt;TabPFN&lt;/code&gt; operates as a core tool inside the wider &lt;strong&gt;FreelanceShield Prediction &amp;amp; Contract Agent&lt;/strong&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;First, the agent extracts structured deal parameters from the SOW and client message (&lt;code&gt;invoice_usd&lt;/code&gt;, &lt;code&gt;net_terms_days&lt;/code&gt;, &lt;code&gt;has_scope_creep&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Next, it invokes &lt;strong&gt;Prior Labs &lt;code&gt;TabPFN-3.5&lt;/code&gt;&lt;/strong&gt; (&lt;code&gt;TabPFNClassifier&lt;/code&gt; / &lt;code&gt;tabpfn_client&lt;/code&gt; via &lt;code&gt;PRIORLABS_API_KEY&lt;/code&gt; from &lt;code&gt;platform.priorlabs.ai&lt;/code&gt; or local CPU/GPU fallback) to perform &lt;strong&gt;in-context tabular inference&lt;/strong&gt; over the freelancer's historical invoice CSV in a single forward pass with zero hyperparameter tuning.&lt;/li&gt;
&lt;li&gt;Finally, the predicted &lt;code&gt;&amp;gt;14-day late-payment probability&lt;/code&gt; dynamically sets the required escrow policy (&lt;code&gt;50%&lt;/code&gt; vs &lt;code&gt;100% Upfront Escrow&lt;/code&gt;) and injects it directly into &lt;strong&gt;Google &lt;code&gt;Gemma&lt;/code&gt;'s&lt;/strong&gt; Change Order counter-proposal:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;numpy&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;tabpfn&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;TabPFNClassifier&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;predict_late_payment_with_tabpfn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;invoice_usd&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;net_terms_days&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;prior_late_count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;has_scope_creep&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;deposit_pct&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;,&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="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
    Runs Prior Labs TabPFN-3.5 zero-shot tabular classification on the freelancer&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;s
    historical invoice CSV ledger inside the wider FreelanceShield prediction agent
    to forecast &amp;gt;14-day payment delay probability and prescribe escrow terms.
    Supports both Prior Labs Cloud API (platform.priorlabs.ai / TabPFN-3.5) and local inference.
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;X_train&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;HISTORICAL_INVOICES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;drop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;columns&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;delayed_over_14d&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]).&lt;/span&gt;&lt;span class="n"&gt;values&lt;/span&gt;
    &lt;span class="n"&gt;y_train&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;HISTORICAL_INVOICES&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;delayed_over_14d&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;values&lt;/span&gt;
    &lt;span class="n"&gt;X_query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;array&lt;/span&gt;&lt;span class="p"&gt;([[&lt;/span&gt;
        &lt;span class="n"&gt;invoice_usd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;net_terms_days&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;prior_late_count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;has_scope_creep&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;deposit_pct&lt;/span&gt;
    &lt;span class="p"&gt;]])&lt;/span&gt;

    &lt;span class="n"&gt;clf&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;TabPFNClassifier&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;device&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cpu&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;clf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;X_train&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y_train&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;prob&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;clf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;predict_proba&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;X_query&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="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="n"&gt;risk_pct&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prob&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;100.0&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;recommended_deposit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;risk_pct&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mf"&gt;75.0&lt;/span&gt; &lt;span class="nf"&gt;else &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;risk_pct&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mf"&gt;40.0&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="mi"&gt;25&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;model&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;Prior Labs TabPFN-3.5&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;late_payment_probability_pct&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;risk_pct&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;recommended_escrow_deposit_pct&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;recommended_deposit&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;
  
  
  3. 1-Click Self-Hosting Blueprint (&lt;code&gt;render.yaml&lt;/code&gt; + &lt;code&gt;Dockerfile&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;For boutique agencies that want a private team instance, the repository includes a declarative &lt;a href="https://github.com/RobinaMirbahar/freelanceshield-open-ai-side-hustle/blob/main/render.yaml" rel="noopener noreferrer"&gt;&lt;code&gt;render.yaml&lt;/code&gt;&lt;/a&gt; and &lt;a href="https://github.com/RobinaMirbahar/freelanceshield-open-ai-side-hustle/blob/main/Dockerfile" rel="noopener noreferrer"&gt;&lt;code&gt;Dockerfile&lt;/code&gt;&lt;/a&gt; to spin up the FastAPI + Gemma + TabPFN microservice in one click.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Does Open Innovation Matter?
&lt;/h2&gt;

&lt;p&gt;For a &lt;strong&gt;Side Hustle&lt;/strong&gt; tool like &lt;strong&gt;FreelanceShield AI&lt;/strong&gt;, open-source and open-weight AI isn't just a philosophical preference - &lt;strong&gt;it is the entire reason the product can legally and economically exist&lt;/strong&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Zero Per-Token Cloud Costs with Open-Weight Google &lt;code&gt;Gemma&lt;/code&gt; (Local-First Architecture):&lt;/strong&gt; Freelancers and agencies benefit from running contract comparisons locally without paying recurring cloud API fees. Running Google's open-weight &lt;code&gt;Gemma&lt;/code&gt; model locally via Ollama + &lt;code&gt;TabPFN&lt;/code&gt; on-device guarantees &lt;strong&gt;0 bytes of client data ever leave the freelancer's machine&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unit Economics That Make a $19/mo Micro-SaaS Profitable:&lt;/strong&gt; When users run contract audits locally on their own laptop GPU/CPU (or a tiny self-hosted container), my marginal per-token API cost is &lt;strong&gt;$0.00&lt;/strong&gt;. I never get wiped out by heavy power users auditing 500-page enterprise RFPs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No Vendor Lock-In or Sudden Deprecations:&lt;/strong&gt; If a freelancer relies on a prompt-engineered workflow to price change orders, a silent closed-model update shouldn't break their billing pipeline. Pinning open-weight checkpoints (&lt;code&gt;Gemma&lt;/code&gt; + &lt;code&gt;TabPFN&lt;/code&gt;) ensures deterministic, auditable results forever.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  My Agent Session
&lt;/h2&gt;

&lt;p&gt;While building &lt;strong&gt;FreelanceShield AI&lt;/strong&gt;, I paired with an agentic coding assistant inside my workspace to rapidly iterate from problem discovery to a deployed dual-model architecture:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Step 1: Identifying the High-ROI Niche:&lt;/strong&gt; I rejected generic "chat with PDF" wrappers and focused on the highest-friction moment in freelancing: &lt;em&gt;how to say "that's out of scope, here is the price" without sounding confrontational.&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Step 2: Combining Google &lt;code&gt;Gemma&lt;/code&gt; + Prior Labs &lt;code&gt;TabPFN-3.5&lt;/code&gt; in a Unified Prediction Agent:&lt;/strong&gt; Instead of forcing a language model to guess numerical invoice risk, I architected a multi-step agent where &lt;strong&gt;Prior Labs' &lt;code&gt;TabPFN-3.5&lt;/code&gt;&lt;/strong&gt; forecasts structured late-payment probability from the freelancer's CSV invoice history and feeds the exact escrow deposit policy into &lt;strong&gt;Google's open-weight &lt;code&gt;Gemma&lt;/code&gt; model&lt;/strong&gt; (for semantic SOW clause matching and diplomatic Change Order copywriting).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Step 3: Zero-Friction Browser Experience:&lt;/strong&gt; To make sure anyone reviewing or testing the tool can experience it immediately, I built a full 3-column interactive workbench in vanilla HTML5 Canvas + ES6 JavaScript that supports both instant browser simulation and live &lt;code&gt;http://localhost:11434&lt;/code&gt; Ollama &lt;code&gt;Gemma&lt;/code&gt; connection.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  My First User
&lt;/h2&gt;

&lt;p&gt;I tested &lt;strong&gt;FreelanceShield AI&lt;/strong&gt; with two fellow independent full-stack developers who do freelance Next.js and AI consulting on the side:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Real Feedback:&lt;/strong&gt; &lt;em&gt;"Usually when a startup founder DMs me on Slack asking for a 'quick dark-mode toggle or webhook' on Thursday night, I just eat the 8 hours because writing a formal change order feels awkward. Being able to paste the SOW and Slack message locally, see the exact clause citation, and copy a friendly counter-proposal with a 50% deposit recommendation in 10 seconds literally saved me $950 on an active sprint."&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Iteration Made from User Feedback:&lt;/strong&gt; Initially, the tool only flagged out-of-scope requests. My first tester pointed out that freelancers also need to reassure clients when a minor bug fix &lt;strong&gt;is&lt;/strong&gt; legitimately in scope - so I added the &lt;strong&gt;✅ In-Scope Verification path&lt;/strong&gt; (&lt;code&gt;Scenario 4&lt;/code&gt;) and the &lt;strong&gt;1-Click Printable Change Order PDF (&lt;code&gt;🖨️ Export Change Order PDF&lt;/code&gt;)&lt;/strong&gt; button!&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Prize Categories
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Best Use of Gemma:&lt;/strong&gt; Uses Google's open-weight &lt;strong&gt;Gemma&lt;/strong&gt; model (&lt;code&gt;gemma4:e4b&lt;/code&gt; / &lt;code&gt;gemma3&lt;/code&gt; via local Ollama inference) to perform 100% private, offline Statement of Work (SOW) clause comparison, unbilled scope-creep hour estimation, and diplomatic Change Order counter-proposal drafting with zero cloud API fees.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Best Use of TabPFN (Prior Labs - &lt;code&gt;TabPFN-3.5&lt;/code&gt;):&lt;/strong&gt; Uses Prior Labs' &lt;strong&gt;&lt;code&gt;TabPFN-3.5&lt;/code&gt;&lt;/strong&gt; (&lt;code&gt;platform.priorlabs.ai&lt;/code&gt; / &lt;code&gt;TabPFNClassifier&lt;/code&gt;) inside a wider multi-step prediction &amp;amp; contract-auditing agent to forecast &lt;code&gt;&amp;gt;14-day invoice payment delays&lt;/code&gt; from the freelancer's historical invoice CSV ledger (&lt;code&gt;5-50 rows&lt;/code&gt;) and dynamically prescribe the upfront escrow/deposit percentage (&lt;code&gt;25%&lt;/code&gt;, &lt;code&gt;50%&lt;/code&gt;, or &lt;code&gt;100%&lt;/code&gt;) injected into Gemma's Change Order counter-proposal.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Best Use of Render:&lt;/strong&gt; Includes a production-ready FastAPI microservice (&lt;code&gt;agent_backend.py&lt;/code&gt;) and declarative &lt;a href="https://github.com/RobinaMirbahar/freelanceshield-open-ai-side-hustle/blob/main/render.yaml" rel="noopener noreferrer"&gt;&lt;code&gt;render.yaml&lt;/code&gt;&lt;/a&gt; blueprint for 1-click private agency self-hosting.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>devchallenge</category>
      <category>hf26challenge</category>
      <category>opensource</category>
      <category>ai</category>
    </item>
    <item>
      <title>I Built a Cozy 60 FPS AI Agent Bakery Game (Built with Gemma 4 &amp; Antigravity) to Teach RAG, Guardrails &amp; Multi-Agent Orchestration</title>
      <dc:creator>Robina Mirbahar</dc:creator>
      <pubDate>Tue, 13 Oct 2026 20:49:38 +0000</pubDate>
      <link>https://dev.to/gde/i-built-a-cozy-60-fps-ai-agent-bakery-game-to-teach-rag-guardrails-context-caching-multi-agent-2ek</link>
      <guid>https://dev.to/gde/i-built-a-cozy-60-fps-ai-agent-bakery-game-to-teach-rag-guardrails-context-caching-multi-agent-2ek</guid>
      <description>&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;Who said learning &lt;strong&gt;AI System Design&lt;/strong&gt; has to be all dark cyberpunk terminal screens and exploding servers?&lt;/p&gt;

&lt;p&gt;I built and open-sourced &lt;strong&gt;Prompt Paws: The Cozy AI Agent Cafe &amp;amp; Bakery&lt;/strong&gt; (architected with &lt;strong&gt;Google Gemma 4 &amp;amp; Antigravity&lt;/strong&gt;) - an interactive &lt;strong&gt;60 FPS AI Agent Architecture Training &amp;amp; Simulation Platform&lt;/strong&gt; disguised as a cozy pastel pastry bakery run by &lt;strong&gt;Robot-Cat Chefs&lt;/strong&gt;! 🐱‍🍳🍰&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Who would use it?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Engineering Teams, Bootcamps &amp;amp; Developer Relations Programs&lt;/strong&gt; training developers on production LLM architecture (where a single uncached system prompt or missing input guardrail can cost thousands of dollars in wasted tokens or latency spikes).&lt;/li&gt;
&lt;li&gt;Instead of static slide decks, &lt;strong&gt;Prompt Paws&lt;/strong&gt; gives teams an interactive, visual sandbox where every pastry station maps &lt;strong&gt;1-to-1&lt;/strong&gt; to a real production AI pattern:&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Cozy Bakery Station&lt;/th&gt;
&lt;th&gt;Critter Order Handled&lt;/th&gt;
&lt;th&gt;Production AI Engineering Layer&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;🥐 Flash Pastry Oven&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Prompt Croissant&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Fast Low-Latency Model (&lt;code&gt;gemini-2.5-flash&lt;/code&gt; / Gemma 4)&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;🍪 Context Cache Jar&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Repeat Owl Menu Query&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Prefix &amp;amp; Context Caching (95% Token Savings)&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;🛡️ Guardrail Flour Sieve&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Spicy Injection Jalapeño&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Input Classifier &amp;amp; Prompt-Injection Sanitizer&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;🍓 Vector Berry Patch&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;RAG Berry Tart&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Vector Search &amp;amp; Fact Grounding (Anti-Hallucination)&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;🧋 Tool-Call Boba Mixer&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Code-Exec Boba Tea&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Deterministic Python Sandbox &amp;amp; Function Calling&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;🍮 Deep-Think Soufflé Oven&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Reasoning Soufflé&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Extended Thinking / System-2 Deliberation&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;🐱 Subagent Sous-Chef Bell&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Parallel Banquet Aura&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Multi-Agent Parallel Delegation (+45% Speed Aura)&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&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%2Fcw1jsx8jbhsl6u31ouxo.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fcw1jsx8jbhsl6u31ouxo.jpg" alt="Prompt Paws: Cozy AI Agent Cafe Banner" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🎮 Live Playable Demo &amp;amp; How to Play in 30 Seconds!
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;🕹️ Play Live in Your Browser (60 FPS HTML5 Canvas):&lt;/strong&gt; 👉 &lt;strong&gt;&lt;a href="https://robinamirbahar.github.io/cozy-ai-agent-cafe-game/" rel="noopener noreferrer"&gt;https://robinamirbahar.github.io/cozy-ai-agent-cafe-game/&lt;/a&gt;&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;🔒 100% Client-Side Simulation ($0.00 API Cost &amp;amp; Zero Keys Required):&lt;/strong&gt; The entire game runs locally inside your browser using a deterministic HTML5 Canvas simulation engine - &lt;strong&gt;no API keys, no sign-ups, and zero paid LLM tokens&lt;/strong&gt; are ever used when you or your team play!&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%2Fyrz55we81659fl0o5tef.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fyrz55we81659fl0o5tef.jpg" alt="How to Play Prompt Paws in 3 Easy Steps" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  🐾 What Is the Core Gameplay Loop?
&lt;/h3&gt;

&lt;p&gt;Think of &lt;strong&gt;Prompt Paws&lt;/strong&gt; as a &lt;strong&gt;cozy Tower-Defense &amp;amp; Kitchen-Management game for AI Agent Architecture&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Customer Pastry Orders (&lt;code&gt;🥐&lt;/code&gt;, &lt;code&gt;🍪&lt;/code&gt;, &lt;code&gt;🌶️&lt;/code&gt;, &lt;code&gt;🍓&lt;/code&gt;, &lt;code&gt;🧋&lt;/code&gt;, &lt;code&gt;🍮&lt;/code&gt;) = Incoming User Prompts&lt;/strong&gt; moving along the bakery conveyor belt toward the &lt;strong&gt;Pickup Window (&lt;code&gt;🛎️&lt;/code&gt;)&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Robot-Cat Kitchen Stations = Real-World AI Engineering Components&lt;/strong&gt; (Fast LLMs, Context Caches, Input Guardrails, RAG Vector DBs, Deterministic Tool Callers, System-2 Reasoning Models, and Multi-Agent Sous-Chefs) that intercept and process prompts before they reach the customer!&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Win / Lose Condition:&lt;/strong&gt; Every order baked by the right AI Chef Station earns &lt;strong&gt;🪙 Star Coins&lt;/strong&gt;! If an unbaked order, an ungrounded &lt;strong&gt;👻 Hallucination Puff&lt;/strong&gt;, or a sneaky &lt;strong&gt;🌶️ Prompt Injection&lt;/strong&gt; slips all the way to the Pickup Window, you lose a &lt;strong&gt;💖 Cafe Reputation Heart&lt;/strong&gt;!&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  🕹️ How to Play in 3 Easy Steps:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;STEP 1 - Pick an AI Chef Station (Left Menu):&lt;/strong&gt; Click a station card on the left sidebar (start with &lt;strong&gt;🥐 Flash Pastry Oven&lt;/strong&gt; for &lt;code&gt;🪙 60&lt;/code&gt;). Check the &lt;strong&gt;Order Forecast chips&lt;/strong&gt; under the level story to see which prompt types are coming!&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;STEP 2 - Click Any &lt;code&gt;[➕ Slot]&lt;/code&gt; Tile on the Map:&lt;/strong&gt; Click one of the 8 pastel counter pads (&lt;code&gt;Slot 1&lt;/code&gt;-&lt;code&gt;Slot 8&lt;/code&gt;) beside the conveyor belt to place your Robot-Cat Chef. (Tip: Click a placed chef anytime to &lt;strong&gt;⬆️ Upgrade&lt;/strong&gt; its baking speed or &lt;strong&gt;🧹 Refund&lt;/strong&gt; it!)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;STEP 3 - Click &lt;code&gt;▶️ Open Cafe&lt;/code&gt; (or &lt;code&gt;✨ Auto-Chef Blueprint&lt;/code&gt;):&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Click &lt;strong&gt;&lt;code&gt;▶️ Open Cafe&lt;/code&gt;&lt;/strong&gt; (or press &lt;code&gt;Spacebar&lt;/code&gt;) to start the shift and watch your Robot-Cat Chefs bake!&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Want to watch an instant demo first?&lt;/strong&gt; Click the purple &lt;strong&gt;&lt;code&gt;✨ Auto-Chef Blueprint&lt;/code&gt;&lt;/strong&gt; button in the top bar on any of the &lt;strong&gt;7 Story Shifts&lt;/strong&gt; and the game will automatically build the optimal Guardrail, Cache, RAG, and Subagent pipeline and run it for you!&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  💻 Open-Source Code
&lt;/h2&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/RobinaMirbahar" rel="noopener noreferrer"&gt;
        RobinaMirbahar
      &lt;/a&gt; / &lt;a href="https://github.com/RobinaMirbahar/cozy-ai-agent-cafe-game" rel="noopener noreferrer"&gt;
        cozy-ai-agent-cafe-game
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Prompt Paws: The Cozy 60 FPS AI Agent Cafe &amp;amp; Bakery Simulation Game teaching RAG, Guardrails, Context Caching &amp;amp; Multi-Agent Workflows — by Robina Mirbahar
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;🐾🥐 Prompt Paws: The Cozy AI Agent Cafe &amp;amp; Bakery&lt;/h1&gt;
&lt;/div&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Author &amp;amp; Architect:&lt;/strong&gt; &lt;a href="https://github.com/RobinaMirbahar" rel="noopener noreferrer"&gt;Robina Mirbahar&lt;/a&gt; (Google Developer Expert in Cloud &amp;amp; AI)&lt;br&gt;
&lt;strong&gt;Focus:&lt;/strong&gt; Interactive Gamified Simulation Teaching RAG, Guardrails, Context Caching &amp;amp; Multi-Agent Workflows&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;🎯 Why I Built Prompt Paws: The Cozy 60 FPS AI Agent Cafe &amp;amp; Bakery (Engineering Purpose &amp;amp; Real-World Value)&lt;/h2&gt;
&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;1. 🐾 Teaching Production AI Engineering Through Cozy Gameplay&lt;/h3&gt;
&lt;/div&gt;
&lt;p&gt;Dense architectural whitepapers on Context Caching, RAG latency, and Prompt Injection Guardrails can intimidate newcomers. I designed &lt;em&gt;Prompt Paws&lt;/em&gt; to turn every core AI engineering pattern into an intuitive mechanic inside a 60 FPS cozy cat cafe.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;2. 🥐 Every Cafe Station Maps 1-to-1 to a Real LLM Subsystem&lt;/h3&gt;

&lt;/div&gt;
&lt;p&gt;In my simulation, the Recipe Book is &lt;strong&gt;Vector RAG&lt;/strong&gt;, the Warm Pastry Case is &lt;strong&gt;Context Caching&lt;/strong&gt; (slashing latency and token cost), the Health Inspector is &lt;strong&gt;Deterministic Guardrails&lt;/strong&gt;, and the Kitchen Crew is &lt;strong&gt;Multi-Agent Orchestration&lt;/strong&gt;.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;3.&lt;/h3&gt;…&lt;/div&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/RobinaMirbahar/cozy-ai-agent-cafe-game" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;





&lt;h2&gt;
  
  
  🛠️ How I Built It
&lt;/h2&gt;

&lt;p&gt;I built &lt;strong&gt;Prompt Paws&lt;/strong&gt; using an open-source, zero-dependency HTML5 Canvas 60 FPS simulation engine (&lt;code&gt;game.js&lt;/code&gt;), a 7-shift progressive AI engineering curriculum (&lt;code&gt;levels.js&lt;/code&gt;), and a procedural WebAudio synthesizer (&lt;code&gt;audio.js&lt;/code&gt;), orchestrated via &lt;strong&gt;Antigravity&lt;/strong&gt; and open agentic workflows.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Order Routing &amp;amp; Guardrail Sanitization (&lt;code&gt;game.js&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;Each station inspects passing orders on the winding bakery conveyor ribbon and only picks up tasks that match its architectural role. Notice how &lt;strong&gt;Spicy Prompt-Injection Jalapeños&lt;/strong&gt; cannot be safely baked by normal ovens until a &lt;strong&gt;Guardrail Flour Sieve&lt;/strong&gt; sanitizes them into safe croissants:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;evaluateKitchenArchitecture&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;lvl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;CAFE_LEVELS&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;currentLevelIdx&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;weights&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;lvl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;orderWeights&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;typesPlaced&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;values&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;placedStations&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;alerts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;weights&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;jalapeno&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;typesPlaced&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;guardrail_sieve&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;alerts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;warn&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Prompt Injection Risk! Place a Guardrail Flour Sieve near Slot 1 or 2 to neutralize spicy raccoon orders!&lt;/span&gt;&lt;span class="dl"&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;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;weights&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tart&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;typesPlaced&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vector_garden&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;alerts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;warn&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hallucination Warning! Berry Tarts need a Vector Berry Patch (RAG) so chefs do not guess facts!&lt;/span&gt;&lt;span class="dl"&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;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;weights&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;boba&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;typesPlaced&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;tool_blender&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;alerts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;warn&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Math/API Alert! Add a Tool-Call Boba Mixer to run deterministic calculations accurately.&lt;/span&gt;&lt;span class="dl"&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;return&lt;/span&gt; &lt;span class="nx"&gt;alerts&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;
  
  
  2. Real-Time AI Architecture Linter ("Chef Whiskers" 🐱‍🍳)
&lt;/h3&gt;

&lt;p&gt;Before you open the cafe doors, &lt;strong&gt;Chef Whiskers (Staff AI Pastry Architect)&lt;/strong&gt; performs live static analysis on your placed stations and warns you about architectural bottlenecks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;evaluateKitchenArchitecture&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;lvl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;CAFE_LEVELS&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;currentLevelIdx&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;weights&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;lvl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;orderWeights&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;typesPlaced&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;values&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;placedStations&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;alerts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;weights&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;jalapeno&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;typesPlaced&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;guardrail_sieve&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;alerts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;warn&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Prompt Injection Risk! Place a Guardrail Flour Sieve near Slot 1 or 2 to neutralize spicy raccoon orders!&lt;/span&gt;&lt;span class="dl"&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;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;weights&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tart&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;typesPlaced&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vector_garden&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;alerts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;warn&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hallucination Warning! Berry Tarts need a Vector Berry Patch (RAG) so chefs do not guess facts!&lt;/span&gt;&lt;span class="dl"&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;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;weights&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;boba&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;typesPlaced&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;tool_blender&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;alerts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;warn&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Math/API Alert! Add a Tool-Call Boba Mixer to run deterministic calculations accurately.&lt;/span&gt;&lt;span class="dl"&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;return&lt;/span&gt; &lt;span class="nx"&gt;alerts&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;h2&gt;
  
  
  🌐 Why Open-Source Visual Sandboxes Matter
&lt;/h2&gt;

&lt;p&gt;Open-source AI models, open agent harnesses, and inspectable system design sandboxes ensure that &lt;strong&gt;every developer - not just giant enterprises - can master safe, cost-efficient AI engineering&lt;/strong&gt;. By making the entire simulation engine, curriculum (&lt;code&gt;levels.js&lt;/code&gt;), and architecture blueprints open-source with zero complex build steps and &lt;strong&gt;$0.00 API token cost&lt;/strong&gt;, any educator or developer community can fork &lt;strong&gt;Prompt Paws&lt;/strong&gt;, add new open-weight model stations (like local Gemma 4 or Ollama nodes), and teach agentic reliability visually!&lt;/p&gt;

</description>
      <category>ai</category>
      <category>gamedev</category>
      <category>javascript</category>
      <category>opensource</category>
    </item>
    <item>
      <title>🚀 Shine on Your AWS Journey: A Fun and Practical Guide to Become an AWS Community Builder! 🌟</title>
      <dc:creator>Robina Mirbahar</dc:creator>
      <pubDate>Mon, 15 Jan 2024 19:39:09 +0000</pubDate>
      <link>https://dev.to/aws-builders/embark-on-your-aws-odyssey-fun-guide-to-becoming-an-aws-community-builder-43p</link>
      <guid>https://dev.to/aws-builders/embark-on-your-aws-odyssey-fun-guide-to-becoming-an-aws-community-builder-43p</guid>
      <description>&lt;h2&gt;
  
  
  Dive into the enchanting realm of AWS Community Leadership!
&lt;/h2&gt;

&lt;p&gt;🌈 Hello, cloud enthusiasts! Ready for a whimsical journey to become an AWS Community Builder? 🧙‍♂️✨ Let's unravel this magical path with fun, facts, and a sprinkle of dad jokes (because, why not?). Buckle up! 🚗💨&lt;/p&gt;

&lt;h2&gt;
  
  
  AWS Community Builders Program Unveiled
&lt;/h2&gt;

&lt;p&gt;Imagine a secret club where AWS tips replace secret handshakes! 🕵️‍♂️🔐 AWS Community Builders: Think of it as Hogwarts for AWS enthusiasts, minus flying brooms (or are they? 🧹✨).&lt;/p&gt;

&lt;p&gt;🎉 &lt;strong&gt;Why Join the Party?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;📚 &lt;strong&gt;Exclusive Knowledge Feast&lt;/strong&gt;: AWS goodies rarer than a unicorn🦄&lt;br&gt;
🤝 &lt;strong&gt;Networking Fiesta&lt;/strong&gt;: AWS who's who mingle. Like LinkedIn, but more cloud, less 'I endorse you for...'.&lt;br&gt;
🌟 &lt;strong&gt;Be the Star&lt;/strong&gt;: Become the Beyoncé of AWS! 🎤💃&lt;br&gt;
🔄 &lt;strong&gt;Feedback Loop-de-loop&lt;/strong&gt;: Whisper sweet (or something) into AWS's ear.&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%2F0hmmptl31klyemt6l8w7.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%2F0hmmptl31klyemt6l8w7.jpeg" alt=" " width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🛣️ &lt;strong&gt;The Yellow Brick Road to AWS Wizardry&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Flaunt Your AWS Wizardry&lt;/strong&gt;&lt;br&gt;
Start a blog, make videos, or speak at events. If Dumbledore did AWS, he'd blog about it! 🧙‍♂️💻&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2: Build Your Digital Kingdom&lt;/strong&gt;&lt;br&gt;
Rule your online presence wisely! Share AWS adventures on &lt;a href="https://dev.to/robinamirbahar"&gt;Dev.to&lt;/a&gt;, &lt;a href="https://www.linkedin.com/in/robinamirbahar/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;, or &lt;a href="https://github.com/robinamirbahar" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;. 🏰🌐&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3: The Quest of the Application&lt;/strong&gt;&lt;br&gt;
Watch the &lt;a href="https://aws.amazon.com/developer/community/community-builders/" rel="noopener noreferrer"&gt;AWS Community Builders program &lt;/a&gt;for the sacred application scroll. 📜✍️&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 4: Engage in the Realm of AWS&lt;/strong&gt;&lt;br&gt;
Sip the elixir of knowledge. Be the Gandalf of the AWS community. 🧙‍♂️🌍&lt;/p&gt;

&lt;p&gt;🎈 &lt;strong&gt;Pro Tips for Aspiring AWS Wizards&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;🔁 &lt;strong&gt;Be Consistent&lt;/strong&gt;: Like brushing your teeth, but for AWS.&lt;br&gt;
🎯 &lt;strong&gt;Quality Over Quantity&lt;/strong&gt;: Nobody likes a half-baked cookie or blog post.&lt;br&gt;
🤗 &lt;strong&gt;Network Like a Pro&lt;/strong&gt;: It's not who you know, but who knows you in AWS!&lt;br&gt;
📚 &lt;strong&gt;Stay Updated&lt;/strong&gt;: AWS changes more than high school fashion.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🎊 Wrapping Up the Party&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Your journey to AWS Community Builder is like a rollercoaster - thrilling, fun, and totally worth it! So, put on your party hats, and let's get this cloud party started! 🎢🎉&lt;/p&gt;

&lt;p&gt;🌟 &lt;strong&gt;Bonus Benefits of AWS Community Builder Program!&lt;/strong&gt; 🎁&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;🌐 &lt;strong&gt;Exclusive Expert Sessions:&lt;/strong&gt; Dive into the knowledge trove with seasoned AWS Community Builders.&lt;/li&gt;
&lt;li&gt;💰 &lt;strong&gt;AWS Credit Bonanza&lt;/strong&gt;: Imagine AWS credits raining down on your 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.amazonaws.com%2Fuploads%2Farticles%2F9l2z1a9n28itz6tqq2lt.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%2F9l2z1a9n28itz6tqq2lt.png" alt=" " width="500" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;🎟️ &lt;strong&gt;AWS re:Invent Ticket Magic&lt;/strong&gt;: Witness the wonders of AWS re:Invent with a 50% discount.&lt;/li&gt;
&lt;li&gt;🚀 &lt;strong&gt;CloudAcademy Access All Area&lt;/strong&gt;s: Elevate your cloud skills with a one-year subscription to CloudAcademy.&lt;/li&gt;
&lt;li&gt;🏆 &lt;strong&gt;Certification Triumph&lt;/strong&gt;: Prove your AWS mastery with a free certification voucher yearly.&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%2Fxl2ponjn05nrqk5ylzjs.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%2Fxl2ponjn05nrqk5ylzjs.png" alt=" " width="800" height="324"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🌈 *&lt;em&gt;Join AWS Community Builder Program Today! *&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Don't just embrace perks; be part of a vibrant community celebrating excellence in the AWS universe. Unleash your cloud adventures and let the benefits rain down like confetti at a cloud party! 🎊☁️&lt;/p&gt;

&lt;p&gt;Remember, AWS Community Builders isn't just a Community; it's a celebration of your commitment to AWS excellence. Embrace the magic, and the community, and let your cloud journey soar to new heights! 🚀🧙‍♂️&lt;/p&gt;

&lt;p&gt;🎉 Comment below with your favourite AWS adventure and share this post! Connect with me on &lt;a href="https://www.linkedin.com/in/robinamirbahar/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; and &lt;a href="https://dev.to/robinamirbahar"&gt;Dev.to&lt;/a&gt; for more cloud fun! Let's make AWS magic together! 🚀🧙‍♂️&lt;/p&gt;

</description>
      <category>aws</category>
      <category>community</category>
      <category>cloud</category>
      <category>containers</category>
    </item>
    <item>
      <title>Code &amp; Canvas: Expressing Myself in the Digital World! 🚀🎨</title>
      <dc:creator>Robina Mirbahar</dc:creator>
      <pubDate>Wed, 03 Jan 2024 18:55:24 +0000</pubDate>
      <link>https://dev.to/robinamirbahar/code-canvas-expressing-myself-in-the-digital-world-3aac</link>
      <guid>https://dev.to/robinamirbahar/code-canvas-expressing-myself-in-the-digital-world-3aac</guid>
      <description>&lt;h2&gt;
  
  
  Introduction:
&lt;/h2&gt;

&lt;p&gt;Coding is not just about logic and syntax; it's an art form that allows us to express our creativity and personality. In this blog, I'll take you on a journey through a coding project that felt like a masterpiece, a canvas where I could splash my emotions and thoughts. 🖌️💻&lt;/p&gt;

&lt;h2&gt;
  
  
  The Project: A Symphony of Pixels 🎵
&lt;/h2&gt;

&lt;p&gt;Picture this: a pixel art generator that brings together my love for coding and passion for vibrant colors. The idea was to create a tool that transforms lines of code into a visual symphony, where every function and variable becomes a stroke of a virtual brush. 🌈&lt;/p&gt;

&lt;h2&gt;
  
  
  Emotions Embedded in the Code:
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Joyful Variables:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I couldn't resist adding some playful variables like &lt;strong&gt;'happyLittlePixel'&lt;/strong&gt; and &lt;strong&gt;'colorfulDreams'&lt;/strong&gt; to spread joy throughout the code. Every time these variables were invoked, it was like injecting a dose of happiness into the project.&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%2F6bm0kuwf1ikupde7m667.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%2F6bm0kuwf1ikupde7m667.png" alt="python" width="800" height="268"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Symphony of Loops:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Loops became my musical notes, creating harmonious patterns across the canvas. The rhythmic dance of &lt;strong&gt;' for'&lt;/strong&gt; and &lt;strong&gt;' while'&lt;/strong&gt; loops echoed the excitement I felt while writing 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%2Fz8sdeaf1adglp3vgtq09.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%2Fz8sdeaf1adglp3vgtq09.png" alt="Javascript" width="799" height="327"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Exceptional Exceptions:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Even error handling became a part of the artistic process. Instead of generic error messages, I crafted exceptions that were like gentle nudges, encouraging users to explore and experiment.&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%2Fo790ia7y1syhuwdub0ui.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%2Fo790ia7y1syhuwdub0ui.png" alt="Java" width="800" height="416"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Thoughts Woven into Comments:&lt;/strong&gt;**&lt;/p&gt;

&lt;p&gt;I didn't stop at just the code; my comments became a diary of thoughts and reflections. It was like leaving love notes for future me, capturing the essence of my creative journey.&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%2Fx0ola2spei53i4htfomx.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%2Fx0ola2spei53i4htfomx.png" alt="python" width="800" height="387"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusion: A Digital Masterpiece&lt;/strong&gt; 🖼️&lt;/p&gt;

&lt;p&gt;In the end, my pixel art generator wasn't just a coding project; it was a piece of my soul woven into the digital fabric. The joy, excitement, and a touch of whimsy embedded in every line of code turned it into a digital masterpiece that reflects who I am as a coder and a dreamer. So, go ahead, let your code be your canvas, and paint your digital emotions with the strokes of syntax! 🎨💻&lt;/p&gt;

</description>
      <category>devresolutions2024</category>
      <category>discuss</category>
    </item>
  </channel>
</rss>
