<?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: Romin Irani</title>
    <description>The latest articles on DEV Community by Romin Irani (@iromin).</description>
    <link>https://dev.to/iromin</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%2F91368%2F280b345a-ce25-4edf-a09f-bdd3b26889a0.png</url>
      <title>DEV Community: Romin Irani</title>
      <link>https://dev.to/iromin</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/iromin"/>
    <language>en</language>
    <item>
      <title>The Antigravity Loop: From Chat to Autonomous Engineering</title>
      <dc:creator>Romin Irani</dc:creator>
      <pubDate>Fri, 10 Jul 2026 07:18:37 +0000</pubDate>
      <link>https://dev.to/googleai/the-antigravity-loop-from-chat-to-autonomous-engineering-295g</link>
      <guid>https://dev.to/googleai/the-antigravity-loop-from-chat-to-autonomous-engineering-295g</guid>
      <description>&lt;p&gt;&lt;em&gt;How to go from pair-programming with AI to fully hands-off autonomous engineering and when each mode actually shines&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%2Fp2uf7j5631vp6au4wo7l.png" class="article-body-image-wrapper"&gt;&lt;img 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%2Fp2uf7j5631vp6au4wo7l.png" width="800" height="447"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Infographic generated by NotebookLM&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Introduction
&lt;/h3&gt;

&lt;p&gt;Here’s a scenario most developers know: you’re building a feature, and you ask an AI assistant to help. You type a prompt, read the response, type another prompt, read, type, read. Twenty exchanges later, the feature works. Your fingers are tired, but you’re happy.&lt;/p&gt;

&lt;p&gt;Now imagine a different scenario: you write a single, detailed brief, like handing a spec to a senior engineer and walk away. You come back 30 minutes later to find the feature fully implemented, tested, deployed, and documented. Your fingers barely moved.&lt;/p&gt;

&lt;p&gt;Both of these are real ways to work with Google Antigravity. The first is &lt;strong&gt;Chat Mode&lt;/strong&gt; , which is conversational, interactive, real-time. The second is &lt;strong&gt;Goal Mode&lt;/strong&gt; , which is autonomous, hands-off, mission-driven.&lt;/p&gt;

&lt;p&gt;Most developers live exclusively in the first. This post will show you when, why, and how to use the second mode i.e. the &lt;strong&gt;Goal mode&lt;/strong&gt; and to get there with the right kind of requirements. This post is not about which mode is better than the other, rather it is an exploration of which modes are best suited to which scenarios.&lt;/p&gt;
&lt;h3&gt;
  
  
  What Exactly Are These Modes?
&lt;/h3&gt;

&lt;p&gt;Before diving into examples, let’s be precise about what each mode means in Antigravity:&lt;/p&gt;
&lt;h4&gt;
  
  
  Chat Mode (The Default)
&lt;/h4&gt;

&lt;p&gt;You type a message. The agent responds. You type again. The conversation proceeds turn by turn. The agent might edit files, run commands, or search the web, but it waits for your input after each step. You see every change as it happens and can redirect immediately.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Think of it like:&lt;/strong&gt; Pair programming with a colleague sitting next to you. You’re both looking at the screen, talking through every decision.&lt;/p&gt;
&lt;h4&gt;
  
  
  Planning Mode (The Middle Ground)
&lt;/h4&gt;

&lt;p&gt;When you ask for something architecturally significant, Antigravity automatically shifts into planning mode. It researches your codebase, creates a detailed implementation_plan.md artifact, and presents it with a "Proceed" button. Nothing changes in your code until you approve. After approval, it executes the plan and creates a &lt;strong&gt;walkthrough&lt;/strong&gt; artifact, summarizing what it did.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Think of it like:&lt;/strong&gt; Hiring a contractor. They survey the site, give you a detailed quote and plan, and only start work after you sign off.&lt;/p&gt;
&lt;h4&gt;
  
  
  Goal Mode (/goal)
&lt;/h4&gt;

&lt;p&gt;You prefix your prompt with /goal. The agent enters a persistent execution loop: research → plan → execute → verify → fix → repeat. It doesn't stop to ask you questions. It handles errors on its own. It may spawn sub-agents for parallel work. It only reports back when it's done (or when it's genuinely stuck and needs human input).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Think of it like:&lt;/strong&gt; Assigning a ticket to a senior engineer. You write the requirements, set the acceptance criteria, and check back when you get the “PR ready for review” notification.&lt;/p&gt;
&lt;h3&gt;
  
  
  The Spectrum of Autonomy
&lt;/h3&gt;

&lt;p&gt;These modes aren’t a binary switch, they’re a dial:&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%2Fmk63wap1oxxxs17jkutk.png" class="article-body-image-wrapper"&gt;&lt;img 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%2Fmk63wap1oxxxs17jkutk.png" width="800" height="98"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For each of the above modes, let us look at Human control v/s Agent autonomy, as shown 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%2Fhgxbqes905pwfx8hcm1x.png" class="article-body-image-wrapper"&gt;&lt;img 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%2Fhgxbqes905pwfx8hcm1x.png" width="800" height="161"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Another way to understand these modes is to understand what the roles of a human v/s Agent are i.e. who is in control during a specific mode and what is each mode best suited for.&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%2Fv8n1d0fbln44ajwuk16x.png" class="article-body-image-wrapper"&gt;&lt;img 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%2Fv8n1d0fbln44ajwuk16x.png" width="800" height="193"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Example 1: Chat Mode — Quick Fixes and Exploration
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;When to use:&lt;/strong&gt; The task is trivial, you want to learn something, or you’re not sure what you want yet.&lt;/p&gt;
&lt;h4&gt;
  
  
  Scenario A: Fix a Bug
&lt;/h4&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Fix the typo in README.md — "recieve" should be "receive"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;What happens:&lt;/strong&gt; The agent makes the single edit and shows you the diff. Done in a few seconds (hopefully). No plan, no artifact, no ceremony.&lt;/p&gt;
&lt;h4&gt;
  
  
  Scenario B: Understand Your Code
&lt;/h4&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Explain how the authentication middleware works in server.js. 
Walk me through the flow step by step.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;What happens:&lt;/strong&gt; The agent reads the file, locates the middleware, and gives you a clear explanation with references to the relevant functions. It doesn’t change anything — it’s pure exploration. This is something Goal Mode may not be good at, since there is no “deliverable” to verify.&lt;/p&gt;
&lt;h4&gt;
  
  
  Scenario C: Brainstorm Ideas
&lt;/h4&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;What are some ways I could improve the onboarding flow in this app? 
The current sign-up takes 4 steps.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;What happens:&lt;/strong&gt; The agent analyzes your codebase, understands the current flow, and proposes improvements with rationale. This is inherently interactive, you want to react, ask follow-ups, and refine. Chat mode is perfect.&lt;/p&gt;
&lt;h4&gt;
  
  
  Why Chat Mode Is Right Here
&lt;/h4&gt;

&lt;p&gt;These tasks share a common trait: &lt;strong&gt;you can’t pre-specify the outcome&lt;/strong&gt;. You don’t know what the agent will say about your code. You don’t know which brainstormed ideas will resonate. You need to see intermediate results before deciding what’s next.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Rule of thumb:&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;If the next step depends on seeing this step’s output, use chat.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;
  
  
  Example 2: Guided Chat — Building Features Interactively
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;When to use:&lt;/strong&gt; You know the feature you want, but the implementation details should be driven by conversation.&lt;/p&gt;
&lt;h4&gt;
  
  
  Real-World Example: Adding Dark Mode
&lt;/h4&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Prompt 1: "Add a dark mode toggle to the header. Use CSS custom 
           properties for theming. Save the preference to 
           localStorage so it persists."

[Agent implements the toggle, CSS variables, localStorage logic]

Prompt 2: "That works, but the transition is jarring. Add a 300ms 
           ease on all color properties."

[Agent adds smooth transition CSS]

Prompt 3: "The icons in the sidebar aren't switching colors. They're 
           using hardcoded hex values."

[Agent finds and replaces the hardcoded colors with CSS variables]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Total interaction:&lt;/strong&gt; 3 prompts, ~5 minutes of your attention. Each prompt built on seeing the result of the previous one.&lt;/p&gt;
&lt;h4&gt;
  
  
  Why Guided Chat Is Right Here
&lt;/h4&gt;

&lt;p&gt;You could have written all three requirements upfront as a goal. But you didn’t know about the jarring transition or the hardcoded icon colors until you saw the first implementation. The iterative nature of guided chat lets you &lt;strong&gt;discover requirements as you go&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This is the most common mode for day-to-day feature development. You have a general direction, but the details emerge through interaction.&lt;/p&gt;
&lt;h3&gt;
  
  
  Example 3: Planning Mode — Architectural Changes
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;When to use:&lt;/strong&gt; The change is significant enough that you want to review the approach before any code changes happen.&lt;/p&gt;
&lt;h3&gt;
  
  
  Scenario: Adding Firebase Authentication
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Add Google Sign-In to the app using Firebase Authentication.
Only authenticated users should see the main content. 
Show a login screen with a Google sign-in button for unauthenticated users.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;What happens automatically:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Research phase:&lt;/strong&gt; The agent audits your codebase. It finds your existing HTML structure, identifies where the login gate should go, checks if any Firebase SDKs are already loaded, and reviews your current routing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Plan creation:&lt;/strong&gt; The agent creates an implementation_plan.md covering:&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Which Firebase SDKs to add&lt;/li&gt;
&lt;li&gt;Where to insert the auth state listener&lt;/li&gt;
&lt;li&gt;How to gate the main content behind onAuthStateChanged&lt;/li&gt;
&lt;li&gt;Security considerations (Firestore rules, protected routes)&lt;/li&gt;
&lt;li&gt;Proposed file changes with estimated line numbers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;3. Review checkpoint:&lt;/strong&gt; The plan appears as an artifact with a “ &lt;strong&gt;Proceed&lt;/strong&gt; ” button. You read exactly what’s going to change before a single line of code is modified.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Execution:&lt;/strong&gt; After you click “ &lt;strong&gt;Proceed&lt;/strong&gt; ,” the agent executes all steps, verifies the login flow works, and creates a walkthrough artifact summarizing what changed.&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%2F6eo5h4ej423b46n2gxp9.png" class="article-body-image-wrapper"&gt;&lt;img 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%2F6eo5h4ej423b46n2gxp9.png" width="800" height="216"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The critical difference from Goal Mode: &lt;strong&gt;the human review checkpoint&lt;/strong&gt; at step 3. Nothing changes in your code until you approve.&lt;/p&gt;
&lt;h4&gt;
  
  
  Why Planning Mode Is Right Here
&lt;/h4&gt;

&lt;p&gt;Authentication is a cross-cutting concern. It touches your HTML structure, JavaScript logic, security rules, and potentially your deployment config. If the agent had started editing without a plan, a wrong assumption about your routing could cascade into a broken app. The plan gives you a chance to catch issues before they become problems.&lt;/p&gt;
&lt;h4&gt;
  
  
  How Planning Mode Gets Triggered
&lt;/h4&gt;

&lt;p&gt;You don’t explicitly ask for it, though you could. Antigravity decides based on the scope of your request and this is what I have typically observed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Simple fixes → direct execution&lt;/li&gt;
&lt;li&gt;New features → may or may not plan (depends on complexity)&lt;/li&gt;
&lt;li&gt;Architectural changes, migrations, multi-file refactors → almost always plans&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you want a plan for something the agent would normally just do, say: “Create a plan for this before implementing.”&lt;/p&gt;
&lt;h3&gt;
  
  
  Example 4: Goal Mode — The Power Move
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;When to use:&lt;/strong&gt; The task is well-defined, you’ve pre-answered every decision, and you want to walk away.&lt;/p&gt;
&lt;h4&gt;
  
  
  The Transition Point: Chat vs. Goal
&lt;/h4&gt;

&lt;p&gt;Let’s compare two approaches to the same task: migrating a REST API integration from fetch to a typed SDK with error handling.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Approach A: Chat Mode (interactive, ~30 minutes)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Exchange 1: "I want to replace raw fetch calls with the 
              official SDK. Where are all the API calls?"
Exchange 2: [Reviews list] "Start with the user endpoints."
Exchange 3: [Reviews changes] "The error handling isn't matching 
              our pattern. Use the AppError class."
Exchange 4: [Reviews fix] "Good. Now do the products endpoints."
Exchange 5: [Reviews changes] "You missed the pagination helper."
Exchange 6: [Reviews fix] "Now the orders endpoints."
Exchange 7: [Reviews changes] "The types are wrong on the 
              response object."
Exchange 8: [Reviews fix] "Looks good. Run the tests."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Total time:&lt;/strong&gt; ~30 minutes of continuous attention across 8 exchanges.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Approach B: Goal Mode (autonomous, ~5 minutes of your time)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;**/goal**

Replace all raw fetch() API calls with the official TypeScript SDK.

## Current State
- API calls are in src/api/*.ts (users.ts, products.ts, orders.ts)
- Raw fetch with manual JSON parsing
- Error handling is inconsistent across files
- Types are defined in src/types/api.ts

## Requirements
1. Install @acme/sdk@^3.0 via npm
2. Replace every fetch() call with the equivalent SDK method
3. Use the existing AppError class (src/utils/errors.ts) for 
   all error handling
4. Ensure all response types match src/types/api.ts
5. Handle pagination using SDK's built-in paginator
6. Remove unused fetch utility functions from src/utils/http.ts

## Constraints
- Don't change any component code that calls these API functions
- Keep the same function signatures (callers shouldn't need to change)
- Don't modify existing types — adapt SDK responses to match them

## Verification
- npm run typecheck passes with zero errors
- npm run test passes (all existing tests should still work)
- grep 'fetch(' src/api/ → zero results
- grep 'AppError' src/api/ → at least one result per file
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Total time:&lt;/strong&gt; ~5 minutes to write the prompt. Walk away.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What the agent does autonomously:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1. Research → Reads all files in src/api/, catalogs every fetch call
2. Plan → Maps each fetch call to its SDK equivalent
3. Execute → Installs SDK, rewrites all three files
4. Verify → Runs typecheck → finds 2 type mismatches → fixes them
5. Re-verify → Runs tests → one test fails due to mock changes → 
                fixes the mock → all tests pass
6. Final grep → Confirms zero remaining fetch() calls
7. Report → Creates walkthrough summarizing all changes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The key difference: in Goal Mode, the type mismatches and failing test would have been caught and fixed &lt;strong&gt;automatically&lt;/strong&gt; during the verify-fix loop. In Chat Mode, those same issues required two more exchanges of your time.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example 5: Goal Mode — Multi-Component Feature
&lt;/h3&gt;

&lt;p&gt;Here’s a more complex goal prompt:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;**/goal**

Add a real-time admin dashboard to the web application.

## Requirements

### Navigation
- Add a "Dashboard" link in the sidebar, visible only to admin users
- Create a new route /admin/dashboard
- Include three tabs: "Users", "Activity", "Revenue"

### Users Tab
- Total registered users (count)
- New users this week (count with trend arrow)
- User growth chart (last 12 weeks, inline SVG bar chart)
- Top 10 most active users (sorted by login count)

### Activity Tab
- Actions per day chart (last 30 days, SVG line chart)
- Most common actions (table with percentages)
- Error rate (percentage with color indicator)

### Revenue Tab
- Monthly revenue chart (last 6 months, SVG bar chart)
- Average order value
- Top selling products (table)

### Design
- Use the existing design system (Tailwind CSS classes)
- Match the existing card component style
- Dark mode compatible
- Responsive — usable on tablet and desktop
- Animate chart elements on render

### Data
- Query existing Firestore collections: users, events, orders
- Use real-time onSnapshot listeners for live updates
- Admin check: user.role === 'admin'

### Constraints
- No external charting libraries (pure SVG)
- Admin-only: gate with role check, redirect non-admins
- Don't modify existing routes or components

### Verification
- Dashboard only accessible when user.role === 'admin'
- All three tabs render without console errors
- Charts display correctly with sample data
- Responsive at 768px viewport width
- npm run build succeeds
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;What makes this a good goal prompt:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Every decision is pre-made (no “should I use Chart.js?” ambiguity)&lt;/li&gt;
&lt;li&gt;Data sources are specified (which collections, which fields)&lt;/li&gt;
&lt;li&gt;Visual style is pinned to existing conventions&lt;/li&gt;
&lt;li&gt;Verification is concrete and testable&lt;/li&gt;
&lt;li&gt;Constraints prevent scope creep&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Anatomy of a Great Goal Prompt
&lt;/h3&gt;

&lt;p&gt;An effective /goal prompt should ideally have these sections:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;**/goal**  

[One-line summary of what you want]

## Current State
What exists today. Tech stack, file locations, relevant architecture.

## Requirements
Numbered list of specific, concrete deliverables.

## Constraints  
What NOT to do. Boundaries. Style rules. "Don't touch X."

## Verification
How the agent knows it's done. Tests to run, greps to check, 
behavior to validate.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  The Decision Pre-Answer Rule
&lt;/h4&gt;

&lt;p&gt;For every place where you’d normally say “yes, do that” or “no, use the other approach” in a chat conversation, &lt;strong&gt;pre-answer it in the goal prompt&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%2Fg64okt40xjwddx537tda.png" class="article-body-image-wrapper"&gt;&lt;img 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%2Fg64okt40xjwddx537tda.png" width="799" height="274"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  What to Include in Verification
&lt;/h4&gt;

&lt;p&gt;Verification criteria are what separate a sub-optimal goal prompt from a good one. Think of them as acceptance tests:&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%2Fqdbv00flhgbnbdoxqpno.png" class="article-body-image-wrapper"&gt;&lt;img 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%2Fqdbv00flhgbnbdoxqpno.png" width="800" height="302"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Without verification criteria, the agent has no way to self-correct. It can’t enter the fix-verify loop because there’s no “verify” step defined.&lt;/p&gt;

&lt;h3&gt;
  
  
  Spec-Driven Development: The Bigger Idea
&lt;/h3&gt;

&lt;p&gt;If the structure of a goal prompt i.e. current state, requirements, constraints, verification looks familiar, it should. It’s a &lt;strong&gt;specification&lt;/strong&gt;. And what we’re really doing with /goal is something that we as software engineers have aspired to for decades now: &lt;strong&gt;writing a spec that executes itself&lt;/strong&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  The Old Way vs. The New Way
&lt;/h4&gt;

&lt;p&gt;Traditional software development has always involved specifications, but there was a gap between the spec and the code:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fx8zyeer62l9zrcz36bzo.png" class="article-body-image-wrapper"&gt;&lt;img 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%2Fx8zyeer62l9zrcz36bzo.png" width="800" height="469"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the traditional flow, the spec is a &lt;strong&gt;communication artifact&lt;/strong&gt; , it tells a human what to build, and the human translates it into code. The translation step is where most bugs are born: misunderstandings, missed edge cases, things the spec assumed were obvious.&lt;/p&gt;

&lt;p&gt;In spec-driven development with Antigravity, the spec is an &lt;strong&gt;execution artifact&lt;/strong&gt;. It doesn’t just describe what to build, it directly drives the building. The “translation step” still exists (the agent interprets your spec), but the feedback loop is immediate: if the agent misinterprets something, the verification step catches it, and the agent self-corrects.&lt;/p&gt;

&lt;h4&gt;
  
  
  What Makes a Spec Executable?
&lt;/h4&gt;

&lt;p&gt;Not every spec works as a goal prompt. The difference between a traditional spec and an executable spec is &lt;strong&gt;verifiability&lt;/strong&gt;. Compare:&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%2F6nlueb2c33vx3wrdcg4u.png" class="article-body-image-wrapper"&gt;&lt;img 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%2F6nlueb2c33vx3wrdcg4u.png" width="800" height="202"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The left column is what humans interpret. The right column is what agents can verify. When every line in your spec has a corresponding check, you’ve written an executable specification.&lt;/p&gt;

&lt;h4&gt;
  
  
  The Spec as the Single Source of Truth
&lt;/h4&gt;

&lt;p&gt;Here’s where it gets powerful. In traditional development, the spec, the code, and the tests are three separate artifacts that can drift apart. The spec says one thing, the code does another, and the tests check a third.&lt;/p&gt;

&lt;p&gt;With a goal prompt:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The spec is the prompt&lt;/strong&gt; and it defines requirements, constraints, and verification.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The code is generated from the spec&lt;/strong&gt; by the agent, not by manual translation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The tests are embedded in the spec&lt;/strong&gt; as &lt;strong&gt;verification criteria&lt;/strong&gt; that run automatically.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There’s one artifact instead of three. And when you need to change behavior, you update the spec and re-run it. You don’t separately update the requirements doc, then the code, then the tests.&lt;/p&gt;

&lt;h4&gt;
  
  
  Leveling Up: Composable Specs
&lt;/h4&gt;

&lt;p&gt;Once you’re comfortable with single goal prompts, you can compose them into multi-phase specifications. This is a possibility and you should try it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Phase 1 Spec: Authentication
  → Verification: users can sign in, auth state persists, 
    protected routes redirect

Phase 2 Spec: Data Layer (depends on Phase 1)
  → Verification: CRUD operations work, security rules enforce 
    auth, real-time updates sync

Phase 3 Spec: UI Dashboard (depends on Phase 2)
  → Verification: charts render, admin gate works, 
    responsive layout, no console errors
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each phase is a self-contained, verifiable spec. Phase 2 doesn’t start until Phase 1’s verification passes. This is dependency-ordered, verified, incremental development and each phase can run autonomously.&lt;/p&gt;

&lt;h4&gt;
  
  
  The Implication for Teams
&lt;/h4&gt;

&lt;p&gt;Spec-driven development changes how teams coordinate. Instead of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Product manager writes a PRD&lt;/li&gt;
&lt;li&gt;Engineer reads the PRD and writes code&lt;/li&gt;
&lt;li&gt;QA reads the PRD and writes tests&lt;/li&gt;
&lt;li&gt;Everyone argues about what the PRD actually meant&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You get:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Product manager and engineer co-write an executable spec&lt;/li&gt;
&lt;li&gt;The spec runs and produces code, tests, and verification in one pass&lt;/li&gt;
&lt;li&gt;Review shifts from “does this code match the spec?” to “is this spec correct?”&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The bottleneck moves from &lt;strong&gt;implementation&lt;/strong&gt; to &lt;strong&gt;specification quality&lt;/strong&gt;. And that’s a much better bottleneck to have, because it’s a thinking bottleneck, not a typing bottleneck.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Slash Commands You Should Know
&lt;/h3&gt;

&lt;p&gt;Beyond /goal, Antigravity offers several slash commands that sit at different points on the autonomy spectrum:&lt;/p&gt;

&lt;h3&gt;
  
  
  /grill-me — The Bridge from Chat to Goal
&lt;/h3&gt;

&lt;p&gt;This is arguably the most important slash command to understand, because it solves the hardest problem in autonomous execution: &lt;strong&gt;how do you know what you don’t know?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When you sit down to write a /goal prompt, you need to pre-answer every decision the agent would otherwise ask you about. But for complex tasks, you don't know what all those decisions are. You don't know what you haven't considered. That's where /grill-me comes in.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/grill-me I want to add multi-tenancy to my SaaS app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The agent reads your codebase, understands the current architecture, and then &lt;strong&gt;interviews you&lt;/strong&gt; with a series of targeted questions — not generic ones, but questions specific to &lt;em&gt;your&lt;/em&gt; code and &lt;em&gt;your&lt;/em&gt; situation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Agent: I've reviewed your app. Here are the key decisions we need 
       to make before I can build this:

1. DATA ISOLATION: Your Firestore is currently a single database.
   Should each tenant get:
   a) Separate Firestore databases (strongest isolation, higher cost)
   b) Separate top-level collections per tenant (moderate isolation)  
   c) A tenantId field on every document (simplest, weakest isolation)

2. URL STRATEGY: Currently your app runs on app.example.com.
   Should tenants get:
   a) Subdomains (acme.app.example.com)
   b) Path-based routing (app.example.com/acme)
   c) Shared URL with tenant selected after login

3. AUTH BOUNDARY: Your Firebase Auth is project-wide. Should:
   a) Users be scoped to a single tenant
   b) Users be able to belong to multiple tenants
   c) Admin users have cross-tenant access

4. DATA ON DELETE: When a tenant is removed, should their data be:
   a) Hard deleted immediately
   b) Soft deleted with a 30-day recovery window
   c) Archived to Cloud Storage

5. EXISTING USERS: You have 340 users in production. How should 
   they be assigned to tenants during migration?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You answer each question. The agent follows up on ambiguous answers. By the end of the interview — typically 5–10 minutes — you’ve surfaced every decision that would have been a blocking question during an autonomous run.&lt;/p&gt;

&lt;h4&gt;
  
  
  From Interview to Executable Spec
&lt;/h4&gt;

&lt;p&gt;Here’s the key: your answers from /grill-me &lt;strong&gt;become your goal prompt&lt;/strong&gt;. The interview output maps directly to the spec structure:&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%2Fl9fklbdx0zbgbzum7oc7.png" class="article-body-image-wrapper"&gt;&lt;img 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%2Fl9fklbdx0zbgbzum7oc7.png" width="798" height="216"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Without /grill-me, you'd discover these decisions the hard way — either by writing an incomplete goal prompt that the agent guesses at (badly), or by having a long chat session where you gradually realize what you missed. /grill-me front-loads all of that discovery into a structured interview.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Think of it this way:&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;Chat is exploration.&lt;/em&gt; &lt;em&gt;/grill-me is structured discovery.&lt;/em&gt; &lt;em&gt;/goal is execution. The best specs come from running&lt;/em&gt; &lt;em&gt;/grill-me first.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  /learn — Persist Patterns
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/learn
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After a productive chat session, use /learn to capture successful patterns. The agent creates a persistent rule or skill so future sessions (including autonomous runs) benefit from what you discovered interactively. For example, after figuring out your project's error handling pattern through chat, /learn saves it so the agent follows the same pattern in future /goal runs.&lt;/p&gt;

&lt;h3&gt;
  
  
  /browser — Web Automation
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/browser Go to https://ai.google.dev and find the current pricing 
for Gemini 2.5 Flash. Summarize it in a table.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The agent launches a browser, navigates pages, reads content, clicks links, fills forms, and takes screenshots. Useful for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Verifying deployed web apps look correct&lt;/li&gt;
&lt;li&gt;Scraping documentation into structured formats&lt;/li&gt;
&lt;li&gt;Testing user flows end-to-end&lt;/li&gt;
&lt;li&gt;Filling out forms and capturing results&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  /schedule — Recurring Tasks
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/schedule Run the test suite every morning at 9am and report any failures
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sets up cron-based agent execution. The agent runs autonomously on a schedule without any intervention. Useful for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Health checks on deployed services&lt;/li&gt;
&lt;li&gt;Periodic report generation&lt;/li&gt;
&lt;li&gt;Automated data syncs&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The Self-Correction Loop: How Autonomous Runs Actually Work
&lt;/h3&gt;

&lt;p&gt;When you use /goal, the agent enters a persistent loop:&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%2Fqydnyoszr53kvye08zs8.png" class="article-body-image-wrapper"&gt;&lt;img 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%2Fqydnyoszr53kvye08zs8.png" width="800" height="1052"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This isn’t just a flowchart, it’s the difference between chat and goal mode.&lt;/p&gt;

&lt;p&gt;Here’s a concrete example:&lt;/p&gt;

&lt;h4&gt;
  
  
  The “Remove Deprecated Feature” Scenario
&lt;/h4&gt;

&lt;p&gt;Imagine you ask the agent to remove a feature. Let’s say, an old notification system that’s been replaced. In &lt;strong&gt;Chat Mode&lt;/strong&gt; , you’d say:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Remove the notification bell feature from the app.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The agent removes the HTML, the JS functions, and the CSS. But let’s say that it &lt;strong&gt;misses&lt;/strong&gt; two stale references:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;initNotifications() is still called in the app's startup() function&lt;/li&gt;
&lt;li&gt;notificationCount is still referenced in the user profile component&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These cause runtime errors. You catch them by testing, report them back, and the agent fixes them one at a time across two more exchanges. Three total interactions to complete what should have been one task.&lt;/p&gt;

&lt;p&gt;In &lt;strong&gt;Goal Mode&lt;/strong&gt; with proper verification:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/goal
Remove the deprecated notification bell feature.

## Requirements
- Remove notification bell HTML from the header
- Remove all notification JS functions
- Remove notification CSS styles
- Remove notification-related state variables

## Verification
- grep -ri 'notification' src/ → zero results (excluding 
  this prompt and git history)
- npm run build succeeds
- No console errors on page load
- App loads normally for both regular and admin users
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The verify step catches the stale references. The fix step removes them. The re-verify step confirms a clean build. The two extra chat exchanges become zero — the loop handles them automatically.&lt;/p&gt;

&lt;h4&gt;
  
  
  What Self-Correction Looks Like
&lt;/h4&gt;

&lt;p&gt;During an autonomous run, the agent:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Runs a command&lt;/strong&gt; → command fails → &lt;strong&gt;reads the error&lt;/strong&gt; → &lt;strong&gt;fixes the code&lt;/strong&gt; →  &lt;strong&gt;retries&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deploys&lt;/strong&gt; → deployment fails → &lt;strong&gt;checks the error log&lt;/strong&gt; → &lt;strong&gt;fixes the config&lt;/strong&gt; → &lt;strong&gt;redeploys&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Greps for leftover code&lt;/strong&gt; → finds stale references → &lt;strong&gt;removes them&lt;/strong&gt; →  &lt;strong&gt;re-greps&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Runs the test suite&lt;/strong&gt; → 2 tests fail → &lt;strong&gt;reads the assertion errors&lt;/strong&gt; → &lt;strong&gt;fixes the code&lt;/strong&gt; → &lt;strong&gt;re-runs tests&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is the core advantage of autonomous execution —  &lt;strong&gt;it doesn’t just run your code, it runs your tests and fixes its own mistakes&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  When Autonomy Fails: Anti-Patterns to Avoid
&lt;/h3&gt;

&lt;p&gt;Goal Mode isn’t magic. Here are real failure modes and how to avoid them. The suggestions given are with a best intention.&lt;/p&gt;

&lt;h4&gt;
  
  
  Anti-Pattern 1: The Vague Goal
&lt;/h4&gt;

&lt;p&gt;❌ &lt;strong&gt;Bad:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/goal Make the app better
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why it fails:&lt;/strong&gt; “Better” is not a verification criterion. The agent will make changes, but it has no way to know when to stop or whether its changes are improvements.&lt;/p&gt;

&lt;p&gt;✅ &lt;strong&gt;Good:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/goal Add loading spinners to all async buttons. Show a spinner 
icon and "Working..." text while operations run. Disable buttons 
during processing to prevent double-clicks.

## Verification
- All async buttons show spinners during their operations
- Buttons are disabled while processing
- Spinners disappear after completion or error
- No console errors
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Anti-Pattern 2: The Under-Constrained Goal
&lt;/h4&gt;

&lt;p&gt;❌ &lt;strong&gt;Bad:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/goal Add charts to the dashboard
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why it fails:&lt;/strong&gt; Should it use Chart.js, D3, or inline SVG? What data should the charts show? What colors? This forces the agent to make design decisions that you’ll likely want to override.&lt;/p&gt;

&lt;p&gt;✅ &lt;strong&gt;Good:&lt;/strong&gt; Pre-answer every design decision — specify the chart approach (inline SVG, no external libraries), data sources (which collections/arrays), visual style (match existing design system), and include concrete verification criteria.&lt;/p&gt;

&lt;h4&gt;
  
  
  Anti-Pattern 3: The Goal That Needs Discussion
&lt;/h4&gt;

&lt;p&gt;❌ &lt;strong&gt;Bad:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/goal Redesign the entire UI to be more modern
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why it fails:&lt;/strong&gt; “Modern” is subjective. The agent will make choices you disagree with, but since it’s running autonomously, it’ll make &lt;em&gt;all&lt;/em&gt; of them before you see any of them. Use chat or /grill-me first to align on the direction.&lt;/p&gt;

&lt;p&gt;✅ &lt;strong&gt;Better approach:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1. Start with chat: "What would a more modern UI look like for this app?"
2. Discuss options, agree on direction
3. Then use /goal with specific design tokens, colors, and patterns
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Anti-Pattern 4: Missing Verification
&lt;/h4&gt;

&lt;p&gt;❌ &lt;strong&gt;Bad:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/goal 

Remove the notification feature from the app

## Requirements
- Remove notification HTML
- Remove notification JS functions
- Remove notification variables
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why it fails:&lt;/strong&gt; No verification step. The agent removes what you listed, but doesn’t check for stale references, the very type of bug that’s easiest to catch with a simple grep.&lt;/p&gt;

&lt;p&gt;✅ &lt;strong&gt;Good:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;## Verification  
- grep -ri 'notification' src/ → zero results
- npm run build succeeds
- No console errors on page load
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Anti-Pattern 5: The Goal That’s Too Large
&lt;/h4&gt;

&lt;p&gt;❌ &lt;strong&gt;Bad:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/goal 

Build a complete e-commerce platform with user auth,
product catalog, shopping cart, checkout, payment processing, 
order management, admin dashboard, and email notifications
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why it fails:&lt;/strong&gt; Too many interacting components. If the auth system has a subtle bug, it cascades into everything else. The agent can’t isolate failures when 8 subsystems are being built simultaneously.&lt;/p&gt;

&lt;p&gt;✅ &lt;strong&gt;Better:&lt;/strong&gt; Break it into phases:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Phase 1: /goal Add user authentication with Google Sign-In
Phase 2: /goal Add product catalog with Firestore backend
Phase 3: /goal Add shopping cart with real-time sync
Phase 4: /goal Add checkout and payment processing
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each phase can be verified independently before moving to the next. You might want to even use /grill-me before coming up with the /goal at each of the phases.&lt;/p&gt;

&lt;h3&gt;
  
  
  When to Use Which Mode: The Decision Matrix
&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%2F9qfrrrxj279oqrkd92qe.png" class="article-body-image-wrapper"&gt;&lt;img 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%2F9qfrrrxj279oqrkd92qe.png" width="799" height="412"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The Litmus Test
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;If you can write down every decision the agent would need to make, use&lt;/em&gt; &lt;strong&gt;&lt;em&gt;/goal&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;. If you'd need to see intermediate results before deciding, use _ **_chat&lt;/em&gt;** &lt;em&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  The Hybrid Approach
&lt;/h3&gt;

&lt;p&gt;In practice, the best workflow is often:&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%2Fd8kn57licmwvr0b326qw.png" class="article-body-image-wrapper"&gt;&lt;img 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%2Fd8kn57licmwvr0b326qw.png" width="795" height="73"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You &lt;strong&gt;chat&lt;/strong&gt; to understand your codebase’s auth patterns&lt;/li&gt;
&lt;li&gt;Use &lt;strong&gt;/grill-me&lt;/strong&gt; to surface edge cases you haven't considered ("what about expired tokens? rate limiting? session management?")&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Chat&lt;/strong&gt; a bit more to decide on the approach&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Write the spec&lt;/strong&gt; as a goal prompt, let &lt;strong&gt;/goal&lt;/strong&gt; execute it autonomously while you focus on something else, and then&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Review&lt;/strong&gt; the walkthrough and diff when it's done.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Practical Tips for Better Autonomous Runs
&lt;/h3&gt;

&lt;h4&gt;
  
  
  1. Start with Chat, Graduate to Goal
&lt;/h4&gt;

&lt;p&gt;Your first time building a feature? Use chat to understand the patterns. The second time you build something similar? Write a goal prompt based on what you learned.&lt;/p&gt;

&lt;h4&gt;
  
  
  2. Use /grill-me Before Writing Complex Goals
&lt;/h4&gt;

&lt;p&gt;Not sure if you’ve thought of everything? The agent interviews you with targeted questions to surface decisions you haven’t considered. Then use the answers to write a comprehensive goal prompt.&lt;/p&gt;

&lt;h4&gt;
  
  
  3. Include File Paths in Goal Prompts
&lt;/h4&gt;

&lt;p&gt;Don’t make the agent guess where things are:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;❌ "Update the main app file"
✅ "Update src/App.tsx and src/components/Header.tsx"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  4. Name Your Data Structures
&lt;/h4&gt;

&lt;p&gt;If the agent needs to work with existing code, tell it the variable names:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;❌ "Use the product list"
✅ "Use the productCatalog[] array from src/data/products.ts"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  5. Specify the Deploy Target
&lt;/h4&gt;

&lt;p&gt;If deployment is part of the goal, be explicit:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;❌ "Deploy it"
✅ "Deploy to Firebase Hosting project my-project-id"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  6. Use /learn After a Chat Session
&lt;/h4&gt;

&lt;p&gt;After a productive chat session, /learn persists successful patterns so future goal runs benefit from what you discovered interactively.&lt;/p&gt;

&lt;h4&gt;
  
  
  7. Set Permissions for Autonomous Runs
&lt;/h4&gt;

&lt;p&gt;For autonomous runs, pre-configure permissions so the agent doesn’t block waiting for approval:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Tool Execution Policy&lt;/strong&gt; : always-proceed (the agent runs commands without asking)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Trusted Workspaces&lt;/strong&gt; : Add your project directory so file operations proceed automatically&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;⚠️ Only use&lt;/em&gt; &lt;em&gt;always-proceed in trusted workspaces where you're comfortable with the agent running commands autonomously.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  The Bigger Picture: How Developer Roles Are Shifting
&lt;/h3&gt;

&lt;p&gt;The distinction between chat and autonomous execution isn’t just a UX feature, it reflects a fundamental shift in what it means to “write code.”&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;In the chat era&lt;/strong&gt; , the developer is a &lt;strong&gt;typist-thinker hybrid&lt;/strong&gt;. You think about what to build, type the code, think about what broke, type the fix. Your value is split between knowing what to do and doing it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;In the autonomous era&lt;/strong&gt; , the developer is a &lt;strong&gt;specification writer and reviewer&lt;/strong&gt;. You think about what to build, write a precise spec, and review the output. Your value shifts entirely to &lt;strong&gt;judgment,&lt;/strong&gt; knowing what to build, how to verify it, and how to catch subtle errors in AI-generated code.&lt;/p&gt;

&lt;p&gt;This isn’t a loss. It’s a liberation. The mental model shifts from:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Think → Type → Debug → Type → Test → Type → Deploy → Type
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Think → Specify → Review → Deploy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The “typing” — the mechanical act of translating intent into code — is the part that gets automated. The thinking, specifying, and reviewing are the parts that remain uniquely human. And those are, arguably, the most intellectually rewarding parts. I hope we have consensus there though some would like to debate what is actually rewarding to them and I will respect that.&lt;/p&gt;

&lt;h3&gt;
  
  
  Summary
&lt;/h3&gt;

&lt;p&gt;The transition from chat to autonomous execution isn’t about trust — it’s about &lt;strong&gt;specification clarity&lt;/strong&gt;. When you can write down exactly what you want, including constraints and verification criteria, you’ve written a goal prompt. When you can’t yet, chat your way there first.&lt;/p&gt;

&lt;p&gt;Start small. Try a /goal on your next well-understood task. See what happens. Then gradually increase the scope as you build confidence in your prompt engineering.&lt;/p&gt;

&lt;p&gt;The dial goes from “fix this typo” to “build this entire feature.” Your job is to figure out, for each task, where to set it.&lt;/p&gt;

&lt;p&gt;A quick table summary to end this article:&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%2Fn5nsm17a18e84j57r9i1.png" class="article-body-image-wrapper"&gt;&lt;img 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%2Fn5nsm17a18e84j57r9i1.png" width="800" height="302"&gt;&lt;/a&gt;&lt;/p&gt;




</description>
      <category>specdrivendevelopmen</category>
      <category>googleantigravity</category>
      <category>autonomouscodingagen</category>
    </item>
    <item>
      <title>The Hackathon Security Guide: How to Vibe-Code Without Burning Down Your Project</title>
      <dc:creator>Romin Irani</dc:creator>
      <pubDate>Thu, 09 Jul 2026 06:33:32 +0000</pubDate>
      <link>https://dev.to/iromin/the-hackathon-security-guide-how-to-vibe-code-without-burning-down-your-project-51dh</link>
      <guid>https://dev.to/iromin/the-hackathon-security-guide-how-to-vibe-code-without-burning-down-your-project-51dh</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;TL;DR&lt;/em&gt;&lt;/strong&gt; &lt;em&gt; — Every year, tens of millions of secrets are leaked to public repos. Automated bots exploit them within&lt;/em&gt; minutes_. This guide gives you the tools, code patterns, and checklists to ship fast_ and &lt;em&gt;ship safe.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fx0l4luzbt7ciik99qwkg.png" class="article-body-image-wrapper"&gt;&lt;img 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%2Fx0l4luzbt7ciik99qwkg.png" width="800" height="447"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Infographic generated by NotebookLM&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Why This Guide Exists
&lt;/h3&gt;

&lt;p&gt;Let’s talk about numbers first. &lt;strong&gt;The numbers are staggering.&lt;/strong&gt; According to GitGuardian’s &lt;a href="https://www.gitguardian.com/state-of-secrets-sprawl-report-2025" rel="noopener noreferrer"&gt;State of Secrets Sprawl 2025&lt;/a&gt; report, &lt;strong&gt;23.8 million new hardcoded secrets&lt;/strong&gt; were leaked on public GitHub repositories in 2024, a &lt;strong&gt;25% increase&lt;/strong&gt; over the previous year. These numbers are likely to only increase in each successive report.&lt;/p&gt;

&lt;p&gt;A recent post from &lt;a href="https://www.linkedin.com/in/harshdattani/" rel="noopener noreferrer"&gt;Harsh Dattani&lt;/a&gt;, who leads the Developer Ecosystems Team in India, does indicate that not paying attention to security might even cost you a chance at the Hackathon.&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%2F925ou9vz2p85c3d553tn.png" class="article-body-image-wrapper"&gt;&lt;img 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%2F925ou9vz2p85c3d553tn.png" width="800" height="856"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;LinkedIn Post Reference: &lt;a href="https://www.linkedin.com/posts/harshdattani_hackathons-buildwithai-cybersecurity-share-7480839977141071872-tVJq" rel="noopener noreferrer"&gt;https://www.linkedin.com/posts/harshdattani_hackathons-buildwithai-cybersecurity-share-7480839977141071872-tVJq&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In the age of “vibe coding”, where we rapidly prompt LLMs to stitch together boilerplate, frontends, and backend connections, it’s incredibly easy to blindly accept generated code, commit it, and leave the front door wide open. AI coding assistants are continously improving and it is less likely that they would frequently generate code with hardcoded placeholder keys that look harmless but become live attack vectors the moment you paste in your real credentials and push. Chances are high that in your hurry to get the entries across the finish line, you end up taking certain shortcuts and hardcode keys and credentials. And worse, you submit that along with your source code, pushed most likely in a public Github repository, as your final entry.&lt;/p&gt;

&lt;p&gt;The attacks mentioned are not hypothetical. Automated bots crawl GitHub 24/7. They can detect and exploit a leaked AWS key within minutes of a commit. The most likely aftereffect … spinning up crypto-mining clusters on your account that can run up tens of thousands of dollars in charges overnight. And unlike ransomware, crypto-mining attacks are designed to be silent, they won’t announce themselves until you check your billing dashboard.&lt;/p&gt;

&lt;p&gt;This guide is an attempt to be your comprehensive blueprint to ensure your team builds safely, avoids massive surprise cloud bills, and doesn’t get disqualified right before the finish line.&lt;/p&gt;
&lt;h3&gt;
  
  
  Part 1: What Gets Leaked — The Threat Map
&lt;/h3&gt;

&lt;p&gt;Before your next commit, audit your codebase for &lt;strong&gt;every&lt;/strong&gt; category below. First-time coders frequently focus only on “API keys” but miss entire classes of sensitive data.&lt;/p&gt;
&lt;h4&gt;
  
  
  1. Cloud Provider Credentials &amp;amp; Service Accounts
&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%2Fuc4psc062g06z3nt9h4f.png" class="article-body-image-wrapper"&gt;&lt;img 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%2Fuc4psc062g06z3nt9h4f.png" width="800" height="327"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Automated bots harvest these 24/7 from GitHub and immediately spin up massive, expensive crypto-mining clusters in your name. A single leaked GCP Service Account Key or AWS root key can generate&lt;/em&gt; &lt;strong&gt;&lt;em&gt;thousands of $$$ in charges&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;within hours.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4&gt;
  
  
  2. Database Connection Strings
&lt;/h4&gt;

&lt;p&gt;Raw connection URIs with embedded plaintext passwords grant the &lt;em&gt;entire internet&lt;/em&gt; read, write, and delete permissions to your database.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# These patterns should NEVER appear in source code:
mongodb+srv://admin:MySecretPass123@cluster0.abc123.mongodb.net
postgresql://postgres:HackathonAdmin2026@db.supabase.co:5432/main
redis://default:sUp3rS3cr3t@redis-12345.c1.us-east-1-2.ec2.cloud.redislabs.com:6379
mysql://root:password@localhost:3306/hackathon_db
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  3. OAuth Secrets, Tokens &amp;amp; Webhook URLs
&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%2F5rjkbkcv7iytyzj1qthm.png" class="article-body-image-wrapper"&gt;&lt;img 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%2F5rjkbkcv7iytyzj1qthm.png" width="799" height="227"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  4. Communication &amp;amp; Messaging Service Credentials
&lt;/h4&gt;

&lt;p&gt;Twilio SIDs, SendGrid API keys, Mailgun tokens, Firebase Cloud Messaging keys … these leaked communication credentials let attackers send high-volume spam under your identity, potentially getting your accounts permanently banned.&lt;/p&gt;

&lt;h4&gt;
  
  
  5. The Forgotten Config Files
&lt;/h4&gt;

&lt;p&gt;These files are committed by accident more often than any hardcoded string:&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%2Fnfqawv05k0zf4h8t1evw.png" class="article-body-image-wrapper"&gt;&lt;img 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%2Fnfqawv05k0zf4h8t1evw.png" width="800" height="362"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  6. The Git History Trap
&lt;/h4&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Deleting a secret from your file and making a new commit does&lt;/em&gt; &lt;strong&gt;&lt;em&gt;NOT&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;remove it. The secret is still fully visible in your Git commit history. Unless the history is explicitly purged, attackers can trivially recover it.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is one of the most common mistakes. You realize a key was hardcoded, you delete it, you commit the fix and you think you’re safe. You are not. Every previous commit is a permanent snapshot. We cover how to properly purge history later in the article.&lt;/p&gt;

&lt;h3&gt;
  
  
  Part 2: Code Blueprints — 14 Framework Examples (Before &amp;amp; After)
&lt;/h3&gt;

&lt;p&gt;Don’t leave configuration to chance. Here are some ways to safely manage secrets across popular frameworks.&lt;/p&gt;

&lt;h4&gt;
  
  
  1. Gemini / Google GenAI SDK (Python)
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;❌ Vulnerable:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="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="n"&gt;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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;AIzaSyA1B2C3D4E5F6G7H8I9J0K_LeakedKey&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;✅ Secure:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&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="n"&gt;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="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;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;p&gt;&lt;strong&gt;📝 Add to **&lt;/strong&gt;.env:**&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GEMINI_API_KEY=your_gemini_api_key_here
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Vector Databases (Pinecone / AI Apps)
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;❌ Vulnerable:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;pinecone&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Pinecone&lt;/span&gt;
&lt;span class="n"&gt;pc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Pinecone&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pcsk_7a8b9c_secret_production_key&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://my-index-12345.svc.us-east-1-aws.pinecone.io&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;✅ Secure:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;pinecone&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Pinecone&lt;/span&gt;

&lt;span class="n"&gt;pc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Pinecone&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="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;PINECONE_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;host&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;PINECONE_HOST&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;📝 Add to **&lt;/strong&gt;.env:**&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PINECONE_API_KEY=your_pinecone_api_key_here
PINECONE_HOST=https://your-index.svc.region.pinecone.io
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Frontend Framework Keys (Vite / React)
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;❌ Vulnerable (&lt;/strong&gt;&lt;strong&gt;firebase.js):&lt;/strong&gt;&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="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;firebaseConfig&lt;/span&gt; &lt;span class="o"&gt;=&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;AIzaSyAsDfGhJkL123456_FakeFirebaseKey&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;authDomain&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hackathon-app.firebaseapp.com&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;projectId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hackathon-app-123&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;✅ Secure:&lt;/strong&gt;&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="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;firebaseConfig&lt;/span&gt; &lt;span class="o"&gt;=&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="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;meta&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;VITE_FIREBASE_API_KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;authDomain&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;meta&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;VITE_FIREBASE_AUTH_DOMAIN&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;projectId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;meta&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;VITE_FIREBASE_PROJECT_ID&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;📝 Add to **&lt;/strong&gt;.env:**&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;VITE_FIREBASE_API_KEY=your_firebase_api_key_here
VITE_FIREBASE_AUTH_DOMAIN=your-app.firebaseapp.com
VITE_FIREBASE_PROJECT_ID=your-project-id
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Firebase API keys are designed to be public identifiers&lt;/strong&gt; , not authorization secrets. They route requests to your project — the real security comes from &lt;strong&gt;Firebase Security Rules&lt;/strong&gt; and &lt;strong&gt;App Check&lt;/strong&gt;. However, you should still:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Restrict your API key&lt;/strong&gt; in the Google Cloud Console (HTTP referrer restrictions, API restrictions)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Never use&lt;/strong&gt;  &lt;strong&gt;allow read, write: if true;&lt;/strong&gt; in production Security Rules&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enable App Check&lt;/strong&gt; to block unauthorized clients&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Even though the key is “public,” an unrestricted key can be abused for quota theft or to access other Google APIs enabled on your project.&lt;/p&gt;

&lt;h4&gt;
  
  
  LLM API Providers (Gemini / Groq / OpenAI)
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;❌ Vulnerable:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="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="n"&gt;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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;AIzaSyA1B2C3D4E5F6G7H8I9J0K_LeakedKey&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;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;generate_content&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;contents&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hello!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;✅ Secure:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&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="n"&gt;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="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;GEMINI_API_KEY&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;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;generate_content&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;contents&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hello!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;📝 Add to **&lt;/strong&gt;.env:**&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GEMINI_API_KEY=your_gemini_api_key_here
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Cloud Object Storage (Google Cloud Storage / AWS S3)
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;❌ Vulnerable:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="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;storage&lt;/span&gt;

&lt;span class="c1"&gt;# DANGER: Loading a service account key file that gets committed to Git
&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;storage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;from_service_account_json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;service-account-key.json&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;bucket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bucket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;my-hackathon-bucket&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;✅ Secure (environment variables):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&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;storage&lt;/span&gt;

&lt;span class="c1"&gt;# Point to the key file via environment variable (file itself is in .gitignore)
&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;GOOGLE_APPLICATION_CREDENTIALS&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;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_SA_KEY_PATH&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="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;storage&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;bucket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bucket&lt;/span&gt;&lt;span class="p"&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;GCS_BUCKET_NAME&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;✅✅ Best Practice (Application Default Credentials — zero keys in code):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="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;storage&lt;/span&gt;

&lt;span class="c1"&gt;# The SDK automatically picks up credentials from:
# 1. Attached service account (on Compute Engine, Cloud Run, Cloud Functions)
# 2. GOOGLE_APPLICATION_CREDENTIALS environment variable
# 3. gcloud auth application-default login (local dev)
# No keys needed in code at all.
&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;storage&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Add to **&lt;/strong&gt;.env:**&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Google Cloud
GOOGLE_APPLICATION_CREDENTIALS=/path/to/your/service-account-key.json
GCS_BUCKET_NAME=your-bucket-name

# AWS (if applicable)
AWS_ACCESS_KEY_ID=your_access_key
AWS_SECRET_ACCESS_KEY=your_secret_key
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Prefer Application Default Credentials (ADC) over service account key files entirely.&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;If you’re running on a Compute Engine VM, Cloud Run service, or Cloud Function, attach a service account directly. The SDK picks up temporary credentials automatically — no key files to leak.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  Chat Webhooks (Discord / Slack Bots)
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;❌ Vulnerable:&lt;/strong&gt;&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;const&lt;/span&gt; &lt;span class="nx"&gt;DISCORD_WEBHOOK&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://discord.com/api/webhooks/123456789/AbCdEfGhIjKlMnOpQrStUvWxYz&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;DISCORD_WEBHOOK&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;New User Registered!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;✅ Secure:&lt;/strong&gt;&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;const&lt;/span&gt; &lt;span class="nx"&gt;DISCORD_WEBHOOK&lt;/span&gt; &lt;span class="o"&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;DISCORD_WEBHOOK_URL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Communication Gateways (Twilio SMS)
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;❌ Vulnerable:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;twilio.rest&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Client&lt;/span&gt;

&lt;span class="n"&gt;account_sid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
&lt;span class="n"&gt;auth_token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;your_raw_auth_token_value_here&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&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;account_sid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;auth_token&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;✅ Secure:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;twilio.rest&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Client&lt;/span&gt;

&lt;span class="n"&gt;account_sid&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;TWILIO_ACCOUNT_SID&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;auth_token&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;TWILIO_AUTH_TOKEN&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&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;account_sid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;auth_token&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Database ORM Frameworks (Prisma Schema)
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;❌ Vulnerable (&lt;/strong&gt;&lt;strong&gt;schema.prisma):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="n"&gt;datasource&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;provider&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;"postgresql"&lt;/span&gt;
  &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;"postgresql://postgres:HackathonAdminPassword2026@db.supabase.co:5432/main"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;✅ Secure:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="n"&gt;datasource&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;provider&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;"postgresql"&lt;/span&gt;
  &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;"DATABASE_URL"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;📝 Add to **&lt;/strong&gt;.env:**&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DATABASE_URL=postgresql://user:password@localhost:5432/my_db
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Maps &amp;amp; Geocoding SDKs (Google Maps)
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;❌ Vulnerable:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://maps.googleapis.com/maps/api/js?key=AIzaSyB4_X_yZ12345&amp;amp;callback=initMap"&lt;/span&gt; &lt;span class="na"&gt;async&lt;/span&gt; &lt;span class="na"&gt;defer&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;✅ Secure (server-side injection at build time):&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For &lt;strong&gt;Vite&lt;/strong&gt; , load the key in JavaScript rather than hardcoding it in HTML:&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="c1"&gt;// maps-loader.js&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;script&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;script&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`https://maps.googleapis.com/maps/api/js?key=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;meta&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;VITE_MAPS_API_KEY&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;amp;callback=initMap`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;defer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;head&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For &lt;strong&gt;Next.js&lt;/strong&gt; , use server-side rendering:&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="c1"&gt;// pages/map.js&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;getServerSideProps&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="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;mapsKey&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;GOOGLE_MAPS_API_KEY&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="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;MapPage&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;mapsKey&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;script&lt;/span&gt; &lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`https://maps.googleapis.com/maps/api/js?key=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;mapsKey&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;amp;callback=initMap`&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nx"&gt;defer&lt;/span&gt; &lt;span class="o"&gt;/&amp;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;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Always restrict Maps API keys&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;in the Google Cloud Console. Set HTTP referrer restrictions to your domain(s) so the key is useless if scraped from your page source.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  Development Bypass Routes (Backdoors)
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;❌ Vulnerable:&lt;/strong&gt;&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="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/login&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;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&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;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;judge_tester&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;password&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;SuperSecretBypass!!!&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;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;token&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;mock_jwt_token_admin&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;✅ Secure:&lt;/strong&gt;&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="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/login&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;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&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;// Test bypass only exists in development mode&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;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;NODE_ENV&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;development&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
        &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt; &lt;span class="o"&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;TEST_USER&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
        &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;password&lt;/span&gt; &lt;span class="o"&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;TEST_PASS&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;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;token&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;generateTestToken&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="c1"&gt;// ... real authentication logic&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Even with environment variables, shipping backdoors is risky.&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;If&lt;/em&gt; &lt;em&gt;NODE_ENV is accidentally left as&lt;/em&gt; &lt;em&gt;development in production, the bypass is live. Consider removing test login routes entirely before submission, or use a dedicated feature flag service.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  Django / Flask Secret Keys (Python)
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;❌ Vulnerable (&lt;/strong&gt;&lt;strong&gt;settings.py):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SECRET_KEY = 'django-insecure-super-secret-key-that-should-not-be-here'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;✅ Secure:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;

&lt;span class="n"&gt;SECRET_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="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;DJANGO_SECRET_KEY&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;SECRET_KEY&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;DJANGO_SECRET_KEY environment variable is not set!&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;h4&gt;
  
  
  Payment Integrations (Stripe)
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;❌ Vulnerable:&lt;/strong&gt;&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;const&lt;/span&gt; &lt;span class="nx"&gt;stripe&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;stripe&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="s1"&gt;sk_live_51H1234567890abcdefghijklmnopqrs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;✅ Secure:&lt;/strong&gt;&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;const&lt;/span&gt; &lt;span class="nx"&gt;stripe&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;stripe&lt;/span&gt;&lt;span class="dl"&gt;'&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;STRIPE_SECRET_KEY&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Stripe live keys (&lt;/em&gt;&lt;em&gt;sk_live_...) provide full access to your payment processing. A leaked key can expose customer payment data and transaction history. Use&lt;/em&gt; &lt;strong&gt;&lt;em&gt;test keys&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;(&lt;/em&gt;&lt;em&gt;sk_test_...) during development, and even those should be in environment variables.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  Docker Compose Secrets
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;❌ Vulnerable (&lt;/strong&gt;&lt;strong&gt;docker-compose.yml):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;db&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;postgres:16&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;POSTGRES_PASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;MyHackathonPassword123&lt;/span&gt;
      &lt;span class="na"&gt;POSTGRES_USER&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;admin&lt;/span&gt;
  &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;DATABASE_URL&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;postgresql://admin:MyHackathonPassword123@db:5432/hackathon&lt;/span&gt;
      &lt;span class="na"&gt;API_KEY&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;AIzaSy_LeakedAgain&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;✅ Secure:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;db&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;postgres:16&lt;/span&gt;
    &lt;span class="na"&gt;env_file&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;.env&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;POSTGRES_PASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${POSTGRES_PASSWORD}&lt;/span&gt;
      &lt;span class="na"&gt;POSTGRES_USER&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${POSTGRES_USER}&lt;/span&gt;
  &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;env_file&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;.env&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;DATABASE_URL&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${DATABASE_URL}&lt;/span&gt;
      &lt;span class="na"&gt;API_KEY&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${API_KEY}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Part 3: Automated Defense — Tools That Catch Secrets Before They Ship
&lt;/h3&gt;

&lt;p&gt;Humans make mistakes. Tools don’t get tired at 3 AM during a hackathon. Set up these automated defenses.&lt;/p&gt;

&lt;h4&gt;
  
  
  Layer 1: Pre-Commit Hooks (Catches secrets before they enter Git)
&lt;/h4&gt;

&lt;p&gt;This is your first and most important line of defense. Install &lt;strong&gt;Gitleaks&lt;/strong&gt; as a pre-commit hook:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Install the pre-commit framework&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;# macOS&lt;/span&gt;
brew &lt;span class="nb"&gt;install &lt;/span&gt;pre-commit

&lt;span class="c"&gt;# pip&lt;/span&gt;
pip &lt;span class="nb"&gt;install &lt;/span&gt;pre-commit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 2: Create **&lt;/strong&gt;.pre-commit-config.yaml in your repo root**&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;repos&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;repo&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://github.com/gitleaks/gitleaks&lt;/span&gt;
    &lt;span class="na"&gt;rev&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v8.30.1&lt;/span&gt; &lt;span class="c1"&gt;# Check GitHub for latest version&lt;/span&gt;
    &lt;span class="na"&gt;hooks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;gitleaks&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 3: Install the hook&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;pre-commit &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now every git commit will automatically scan for secrets and &lt;strong&gt;block the commit&lt;/strong&gt; if any are found.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hackathon shortcut:&lt;/strong&gt; If you don’t want to set up pre-commit, you can run Gitleaks manually before pushing:&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&lt;/span&gt;
brew &lt;span class="nb"&gt;install &lt;/span&gt;gitleaks

&lt;span class="c"&gt;# Scan your repo&lt;/span&gt;
gitleaks detect &lt;span class="nt"&gt;--source&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="nt"&gt;--verbose&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Layer 2: GitHub Push Protection (Catches secrets at the remote)
&lt;/h4&gt;

&lt;p&gt;GitHub automatically scans every push to public repositories and blocks commits containing recognized secret patterns (API keys, Stripe keys, etc.). This is &lt;strong&gt;enabled by default&lt;/strong&gt; on public repos.&lt;/p&gt;

&lt;p&gt;For private repos: Go to &lt;strong&gt;Settings → Code security → Secret scanning&lt;/strong&gt; and enable both &lt;strong&gt;Secret scanning&lt;/strong&gt; and &lt;strong&gt;Push protection&lt;/strong&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Layer 3: CI/CD Pipeline Scanning (Final safety net)
&lt;/h4&gt;

&lt;p&gt;Add Gitleaks to your GitHub Actions workflow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# .github/workflows/security.yml&lt;/span&gt;
&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Secret Scan&lt;/span&gt;
&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;pull_request&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;gitleaks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v4&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;fetch-depth&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;gitleaks/gitleaks-action@v2&lt;/span&gt;
        &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;GITHUB_TOKEN&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.GITHUB_TOKEN }}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Defense Layers Summary
&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%2Fd9995wlpppgvpn0vp3ig.png" class="article-body-image-wrapper"&gt;&lt;img 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%2Fd9995wlpppgvpn0vp3ig.png" width="800" height="151"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Part 4: The AI Guardrail — System Prompt for Vibe Coding
&lt;/h3&gt;

&lt;p&gt;If you rely on AI coding assistants (Antigravity, Claude, Claude, ChatGPT, Gemini, GitHub Copilot) to write your application code, you can block raw secrets at the source. Paste this into your AI assistant’s system rules or your initial chat prompt:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;You are an expert, security-conscious Lead Developer. We are building a
rapid prototype / hackathon project, but infrastructure security is a
non-negotiable core feature.

STRICT GUARDRAILS for all code generation:

1. NEVER hardcode API keys, passwords, private tokens, connection strings,
   webhook URLs, or any environment secrets directly into the code.

2. When a credential is required, ALWAYS use the standard environment
   variable pattern for the language/framework:
   - Node.js: process.env.VARIABLE_NAME
   - Python: os.environ.get("VARIABLE_NAME")
   - Vite/React: import.meta.env.VITE_VARIABLE_NAME
   - Go: os.Getenv("VARIABLE_NAME")
   - Prisma: env("VARIABLE_NAME")

3. Every time you generate code that requires a secret, explicitly list the
   key-value pairs I need to add to my local .env file.

4. Provide a .env.example file with placeholder names (never real values).

5. If I accidentally paste code containing what appears to be a live API
   key, FLAG IT IMMEDIATELY and remind me to rotate the credential.

6. When generating Docker or docker-compose files, use env_file or
   variable substitution — never inline secrets.

7. When generating .gitignore, always include: .env, .env.local,
   .env.production, *.pem, *.key, serviceAccountKey.json, and
   any other credential files relevant to the project.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Part 5: Emergency Response — When You Leak a Secret
&lt;/h3&gt;

&lt;p&gt;It’s 2 AM. You just realized you pushed a commit with your live keys 6 hours ago. Here’s the emergency protocol:&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 1: ROTATE IMMEDIATELY (Do this FIRST)
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Do not skip this step.&lt;/strong&gt; Do not “clean up the code first.” Assume the secret has already been harvested.&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%2Flgzatjrxfvxf0lwi9ptd.png" class="article-body-image-wrapper"&gt;&lt;img 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%2Flgzatjrxfvxf0lwi9ptd.png" width="799" height="291"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 2: Check for Unauthorized Usage
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Google Cloud:&lt;/strong&gt; Check Cloud Audit Logs for unexpected API calls. Check Billing reports for unusual charges.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AWS:&lt;/strong&gt; Check CloudTrail for unexpected API calls. Check the Billing dashboard for unusual charges.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Azure:&lt;/strong&gt; Check Activity Log and Cost Management.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stripe:&lt;/strong&gt; Check the Events log for unauthorized transactions.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Step 3: Remove from Git History
&lt;/h4&gt;

&lt;p&gt;Simply deleting the line and making a new commit is &lt;strong&gt;not enough&lt;/strong&gt;. Use git filter-repo (the modern, Git-recommended replacement for the deprecated git filter-branch):&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&lt;/span&gt;
pip &lt;span class="nb"&gt;install &lt;/span&gt;git-filter-repo

&lt;span class="c"&gt;# Clone a fresh mirror copy (required by git filter-repo)&lt;/span&gt;
git clone &lt;span class="nt"&gt;--mirror&lt;/span&gt; https://github.com/your-org/your-repo.git
&lt;span class="nb"&gt;cd &lt;/span&gt;your-repo.git

&lt;span class="c"&gt;# Option A: Remove an entire file from history&lt;/span&gt;
git filter-repo &lt;span class="nt"&gt;--path&lt;/span&gt; .env &lt;span class="nt"&gt;--invert-paths&lt;/span&gt;

&lt;span class="c"&gt;# Option B: Replace a specific secret string&lt;/span&gt;
&lt;span class="c"&gt;# Create replacements.txt with format: literal:OLD_SECRET==&amp;gt; ***REDACTED***&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'literal:AKIAIOSFODNN7EXAMPLE==&amp;gt; ***REDACTED***'&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /tmp/replacements.txt
git filter-repo &lt;span class="nt"&gt;--replace-text&lt;/span&gt; /tmp/replacements.txt

&lt;span class="c"&gt;# Force push the cleaned history&lt;/span&gt;
git push origin &lt;span class="nt"&gt;--force&lt;/span&gt; &lt;span class="nt"&gt;--all&lt;/span&gt;
git push origin &lt;span class="nt"&gt;--force&lt;/span&gt; &lt;span class="nt"&gt;--tags&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;After force-pushing, every team member must re-clone the repository. If anyone pushes from their old local copy, the secret will be re-introduced into the history.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Part 6: Protect Your Wallet — Cloud Billing Safeguards
&lt;/h3&gt;

&lt;p&gt;Leaked keys are the #1 cause of surprise cloud bills at hackathons. Even if you’re using free-tier credits, set these up immediately.&lt;/p&gt;

&lt;h4&gt;
  
  
  Set Budget Alerts on Day Zero
&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%2Fsq74pp2q7lkwwriuxwu1.png" class="article-body-image-wrapper"&gt;&lt;img 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%2Fsq74pp2q7lkwwriuxwu1.png" width="799" height="174"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Hackathon Cost Hygiene
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Use the smallest instance sizes&lt;/strong&gt; (e2-micro on GCP, t3.micro on AWS) unless you specifically need more.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Set calendar reminders&lt;/strong&gt; to delete resources after the hackathon.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tag all resources&lt;/strong&gt; with project=hackathon-name so you can identify orphaned resources.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Disable unused APIs&lt;/strong&gt; in your cloud console.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Never use root/owner credentials&lt;/strong&gt;  — create a limited IAM user or service account with only the permissions you need.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Restrict Your API Keys
&lt;/h4&gt;

&lt;p&gt;Even keys that are designed to be client-facing (like Firebase or Google Maps keys) should be &lt;strong&gt;restricted&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%2F2gmywaxhthi4cybnrtb9.png" class="article-body-image-wrapper"&gt;&lt;img 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%2F2gmywaxhthi4cybnrtb9.png" width="800" height="182"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Configure these in the &lt;strong&gt;Google Cloud Console → APIs &amp;amp; Services → Credentials&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Part 7: The Bulletproof Submission Checklist
&lt;/h3&gt;

&lt;p&gt;Before your team clicks “Submit,” take five minutes to walk through this loop. Print this out. Tape it to your monitor.&lt;/p&gt;

&lt;h4&gt;
  
  
  Pre-Submission Audit
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;.gitignore exists&lt;/strong&gt; and contains: .env, .env.local, .env.production, *.pem, *.key, serviceAccountKey.json, config.json (if it has secrets)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;.env.example is included&lt;/strong&gt; in the repo with descriptive placeholder names (see template below)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No secrets in&lt;/strong&gt;  &lt;strong&gt;docker-compose.yml&lt;/strong&gt;  — uses env_file or ${VARIABLE} substitution&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No secrets in CI/CD config&lt;/strong&gt;  — all secrets are in GitHub Secrets / environment variables&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No test backdoors&lt;/strong&gt; with hardcoded credentials remain in the code&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Run the comprehensive grep scan&lt;/strong&gt; (see below)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Run Gitleaks&lt;/strong&gt; (gitleaks detect --source . --verbose)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;API keys are restricted&lt;/strong&gt; in cloud console (referrer, IP, API scope)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Budget alerts are set&lt;/strong&gt; on all cloud accounts&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;README includes setup instructions&lt;/strong&gt; that reference the .env.example&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  .env.example Template
&lt;/h4&gt;

&lt;p&gt;Ship this in your repo root so judges and reviewers can set up your project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# ==========================================
# PROJECT CONFIGURATION TEMPLATE
# ==========================================
# Copy this file to .env and fill in your values.
# DO NOT commit the .env file.
# ==========================================

# --- Server ---
PORT=8080
NODE_ENV=development

# --- Database ---
DATABASE_URL=

# --- AI / LLM ---
GEMINI_API_KEY=
OPENAI_API_KEY=
GROQ_API_KEY=

# --- Vector Database ---
PINECONE_API_KEY=
PINECONE_HOST=

# --- Cloud Storage ---
AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_REGION=us-east-1

# --- Authentication ---
JWT_SECRET=
GOOGLE_OAUTH_CLIENT_ID=
GOOGLE_OAUTH_CLIENT_SECRET=

# --- Communication ---
TWILIO_ACCOUNT_SID=
TWILIO_AUTH_TOKEN=
DISCORD_WEBHOOK_URL=

# --- Payments ---
STRIPE_SECRET_KEY=
STRIPE_PUBLISHABLE_KEY=

# --- Firebase (client-side, restrict in Cloud Console) ---
VITE_FIREBASE_API_KEY=
VITE_FIREBASE_AUTH_DOMAIN=
VITE_FIREBASE_PROJECT_ID=
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Leave values &lt;strong&gt;blank&lt;/strong&gt; (not with fake-looking values like AIzaSyYourKeyHere that could be mistaken for real keys). Use descriptive variable names so it's obvious what each one is for.&lt;/p&gt;

&lt;h4&gt;
  
  
  Comprehensive Pre-Push Grep Scan
&lt;/h4&gt;

&lt;p&gt;Run this in your terminal from the project root. It searches for common secret patterns across your codebase, ignoring common false-positive directories:&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;# Quick scan — looks for common secret patterns&lt;/span&gt;
git &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-inE&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="s1"&gt;'sk_live|sk_test|AKIA[0-9A-Z]{16}|AIzaSy|ghp_|gho_|glpat-|xoxb-|xoxp-|hooks\.slack\.com|discord\.com/api/webhooks|mongodb\+srv://|postgresql://[^]*:[^]*@|-----BEGIN (RSA |EC )?PRIVATE KEY|pcsk_|gsk_'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="s1"&gt;':!node_modules'&lt;/span&gt; &lt;span class="s1"&gt;':!.git'&lt;/span&gt; &lt;span class="s1"&gt;':!*.lock'&lt;/span&gt; &lt;span class="s1"&gt;':!package-lock.json'&lt;/span&gt;

&lt;span class="c"&gt;# Broader scan — catches environment variable assignments with values&lt;/span&gt;
git &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-inE&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="s1"&gt;'(api[_-]?key|secret|password|token|credential|auth[_-]?token)\s*[:=]\s*["\x27][A-Za-z0-9_\-/.+]{8,}'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="s1"&gt;':!node_modules'&lt;/span&gt; &lt;span class="s1"&gt;':!.git'&lt;/span&gt; &lt;span class="s1"&gt;':!*.lock'&lt;/span&gt; &lt;span class="s1"&gt;':!*.md'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The original blog’s&lt;/strong&gt;  &lt;strong&gt;git grep -i "key|secret|password|token|sk_" is too broad&lt;/strong&gt; and will produce hundreds of false positives (variable names, comments, documentation). The patterns above target actual secret &lt;em&gt;values&lt;/em&gt;, not just keywords.&lt;/p&gt;

&lt;h3&gt;
  
  
  Part 8: Quick-Reference Cheat Sheet
&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%2Fr43589nqno59qad54lsg.png" class="article-body-image-wrapper"&gt;&lt;img 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%2Fr43589nqno59qad54lsg.png" width="800" height="531"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Part 9: The Minimal .gitignore Every Hackathon Project Needs
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# === Secrets &amp;amp; Config ===
.env
.env.*
!.env.example
*.pem
*.key
*.p12
*.pfx
serviceAccountKey.json
google-services.json
GoogleService-Info.plist
credentials.json
secrets.json
config.local.json

# === Dependencies ===
node_modules/
vendor/
__pycache__ /
*.pyc
.venv/
venv/

# === Build Outputs ===
dist/
build/
.next/
out/

# === IDE ===
.vscode/
.idea/
*.swp
*.swo
.DS_Store
Thumbs.db

# === Terraform ===
*.tfvars
.terraform/
terraform.tfstate*
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Final Words
&lt;/h3&gt;

&lt;p&gt;The five minutes you spend separating your logic from your secrets will save you from:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Surprise cloud bills that can reach thousands of dollars&lt;/li&gt;
&lt;li&gt;Hackathon disqualification for security violations&lt;/li&gt;
&lt;li&gt;The stress of rotating every credential at 3 AM&lt;/li&gt;
&lt;li&gt;The embarrassment of explaining to your team why the Cloud bill is $12,000&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The tools exist. The patterns are simple. The checklists are right here. Use them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Keep building. Keep shipping. Keep it secure.&lt;/strong&gt;&lt;/p&gt;




</description>
      <category>vibecoding</category>
      <category>googlecloudplatform</category>
      <category>hackathon</category>
      <category>hackathonsecurity</category>
    </item>
    <item>
      <title>Mastering Gemini Computer Use : A Comprehensive Hands-on Guide</title>
      <dc:creator>Romin Irani</dc:creator>
      <pubDate>Fri, 26 Jun 2026 10:34:30 +0000</pubDate>
      <link>https://dev.to/googleai/mastering-gemini-computer-use-a-comprehensive-hands-on-guide-3emg</link>
      <guid>https://dev.to/googleai/mastering-gemini-computer-use-a-comprehensive-hands-on-guide-3emg</guid>
      <description>&lt;p&gt;&lt;a href="https://blog.google/innovation-and-ai/models-and-research/gemini-models/introducing-computer-use-gemini-3-5-flash/" rel="noopener noreferrer"&gt;Gemini Computer Use&lt;/a&gt; lets you build AI agents that control real screens by looking at screenshots and deciding what to click, type, or scroll, just like a human would.&lt;/p&gt;

&lt;p&gt;You can read the announcement post below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.google/innovation-and-ai/models-and-research/gemini-models/introducing-computer-use-gemini-3-5-flash/" rel="noopener noreferrer"&gt;Introducing computer use in Gemini 3.5 Flash&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This tutorial walks you through five progressive steps (from “Hello Screenshot” to Gemini Enterprise Agent Platform), then shows five real-world use cases. All code is included and runnable.&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%2Fo1pcyqurqouy2i9h7r2t.png" class="article-body-image-wrapper"&gt;&lt;img 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%2Fo1pcyqurqouy2i9h7r2t.png" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  What is Computer Use?
&lt;/h3&gt;

&lt;p&gt;If you’ve ever written a Selenium test or a Puppeteer script, you know the script and the friction that comes with it. You spend hours crafting CSS selectors, XPath expressions, and fragile wait conditions. Then one day, the website changes a class name, and everything breaks. This is the fragile nature of selector-based automation, where it depends on the implementation details of the UI rather than what’s actually visible on the screen.&lt;/p&gt;

&lt;p&gt;And there’s a deeper problem. Not every application exposes an API. Legacy enterprise software, desktop apps, mobile interfaces , there’s an enormous surface area of software that can only be operated by a human looking at a screen and clicking around.&lt;/p&gt;

&lt;h4&gt;
  
  
  The Solution: AI That Sees
&lt;/h4&gt;

&lt;p&gt;Gemini Computer Use takes a radically different approach. Instead of parsing HTML or querying the DOM, the model &lt;strong&gt;looks at a screenshot&lt;/strong&gt; and decides what to do, &lt;strong&gt;exactly the way a human would&lt;/strong&gt;. It doesn’t need selectors. It doesn’t need APIs. It just needs eyes.&lt;/p&gt;

&lt;p&gt;The paradigm is beautifully simple: &lt;strong&gt;Observe → Think → Act&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%2F8ah30c8la0t67b9a9rkl.png" class="article-body-image-wrapper"&gt;&lt;img 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%2F8ah30c8la0t67b9a9rkl.png" width="800" height="90"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Observe:&lt;/strong&gt; Capture a screenshot of the current screen state&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Think:&lt;/strong&gt; Send it to Gemini 3.5 Flash, which analyzes the visual content and decides the next action&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Act:&lt;/strong&gt; Execute the action (click a button, type text, scroll down), then capture a new screenshot and loop back&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This loop continues &lt;strong&gt;until the model decides the task is complete and responds with text instead of a function call&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  How Computer Use Works: Brain, Eyes, and Hands
&lt;/h3&gt;

&lt;p&gt;Every Computer Use agent has three parts:&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%2Fmbcjidhb76sw1cyk1bf1.png" class="article-body-image-wrapper"&gt;&lt;img 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%2Fmbcjidhb76sw1cyk1bf1.png" width="798" height="230"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Brain is always the same — Gemini 3.5 Flash. But the &lt;strong&gt;Hands change&lt;/strong&gt; depending on what you’re controlling:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌─────────────────────────────────────────────────────────────────┐
│ 🧠 BRAIN (always the same) │
│ Gemini 3.5 Flash │
│ "Look at this screenshot, what should I do?" │
└──────────────────────────┬──────────────────────────────────────┘
                           │
              Model returns: click(x=396, y=185)
                           │
          ┌────────────────┼────────────────┐
          ▼ ▼ ▼
   🖐️ Browser 🖐️ Mobile 🖐️ Enterprise
   Playwright ADB CDP Sandbox
   page.mouse adb shell Remote browser
   .click(506,148) input tap in the cloud
                      506 148
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why this matters:&lt;/strong&gt; The model doesn’t know or care what “hands” you’re using. It just sees screenshots and returns actions. You can swap Playwright for Selenium, ADB for a physical device, or a local browser for a cloud sandbox — the model’s output is identical. The only thing that changes is the environment parameter you declare (browser, mobile, or desktop), which tells the model what kind of screen it's looking at.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Gemini 3.5 Flash is Special
&lt;/h3&gt;

&lt;p&gt;Computer Use isn’t a separate model or a bolted-on capability. In gemini-3.5-flash, it's a native tool, declared alongside other tools like function calling and code execution. This design decision has key implications and its worthwhile to understand them:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Multi-tool composition:&lt;/strong&gt; The model can interleave browser actions with custom function calls in the same conversation. Click a button, then call save_product() to store data, then scroll down for more.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Three environments:&lt;/strong&gt; One model supports ENVIRONMENT_BROWSER, ENVIRONMENT_MOBILE, and ENVIRONMENT_DESKTOP. You declare the environment and the model adapts its available actions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Thinking mode:&lt;/strong&gt; You can enable ThinkingConfig(include_thoughts=True) to see the model's reasoning before each action, invaluable for debugging.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Key Technical Concepts
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Normalized Coordinates (0–999):&lt;/strong&gt; The model doesn’t know your screen resolution. Instead, it outputs coordinates in a normalized 0–999 range. You convert them to pixels with:&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;pixel&lt;/span&gt; &lt;span class="o"&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;normalized&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;screen_dimension&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For a &lt;strong&gt;1280×800 viewport, coordinate&lt;/strong&gt; &lt;strong&gt;(500, 500) maps to pixel&lt;/strong&gt; &lt;strong&gt;(640, 400) — the centre of the screen&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The&lt;/strong&gt;  &lt;strong&gt;intent Field:&lt;/strong&gt; Each function call includes an intent string describing &lt;strong&gt;what the model is trying to achieve&lt;/strong&gt; , not just the mechanical action. This is crucial if you try to debug the whole flow.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Safety Decisions:&lt;/strong&gt; When the model encounters potentially sensitive actions (making a purchase, sending a message, deleting data), it includes a safety_decision object requesting explicit user confirmation.&lt;/p&gt;

&lt;h4&gt;
  
  
  What Changed from Legacy to Current
&lt;/h4&gt;

&lt;p&gt;The previous gemini-2.5-computer-use-preview model was an early experiment with a separate API surface. The current gemini-3.5-flash approach integrates Computer Use as a standard tool. This means the same model, the same SDK, and the same generate_content() call, that you already know.&lt;/p&gt;

&lt;h4&gt;
  
  
  Two Paths: Gemini API vs Enterprise Platform
&lt;/h4&gt;

&lt;p&gt;There are two ways to use Gemini Computer Use, and which one you choose depends on where you are in the development lifecycle.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Gemini API (ai.google.dev)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The fastest path from zero to working agent. Grab an API key, pip install the SDK, and you’re running. You build your own execution environment (Playwright for browsers, ADB for Android), which gives you maximum flexibility and zero cloud dependencies.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Enterprise Agent Platform (Vertex AI)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When you’re ready for production, Vertex AI adds IAM-based authentication, managed browser sandboxes (no local browser needed), VPC Service Controls, audit logging, and all the enterprise trimmings. The important part? The code is almost identical. You change one line.&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%2Fam79k5pm8zaty3t1slvl.png" class="article-body-image-wrapper"&gt;&lt;img 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%2Fam79k5pm8zaty3t1slvl.png" width="800" height="318"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The migration between paths is a single-line change in client construction:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Before — Gemini API (prototyping)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Gemini API (prototyping)
&lt;/span&gt;&lt;span class="n"&gt;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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;YOUR_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;p&gt;&lt;strong&gt;After — Vertex AI (production)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# That's it — that's the migration
&lt;/span&gt;&lt;span class="n"&gt;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;vertexai&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;project&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;my-project&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;location&lt;/span&gt;&lt;span class="o"&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="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Prerequisites &amp;amp; Setup
&lt;/h3&gt;

&lt;p&gt;In this section, we will identify the software that we need. This completely depends on what use cases and scenarios that you are interested in, while using Gemini Computer Use.&lt;/p&gt;

&lt;p&gt;The table given in the section &lt;strong&gt;What You Need&lt;/strong&gt; identifies the requirement and which step/use case that you need it for. For e.g. if you are not interested in Android app scenarios or running this on Google Cloud, you can simply do with Python 3.10+ and Gemini API Key only. Each of the steps and use cases are mentioned clearly in the article. So as you go along, remember to have these requirements handy.&lt;/p&gt;

&lt;h4&gt;
  
  
  What You Need
&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%2Fdkqn4f0kklhsqhikfl5k.png" class="article-body-image-wrapper"&gt;&lt;img 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%2Fdkqn4f0kklhsqhikfl5k.png" width="800" height="226"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Step-by-Step Installation
&lt;/h4&gt;

&lt;p&gt;The examples are code heavy and hence I have made a code repository available for you. The tutorial too goes into each of the folders i.e. steps or use cases in the repository, and you can follow the steps to run the examples.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/rominirani/computer-use-tutorial" rel="noopener noreferrer"&gt;GitHub - rominirani/computer-use-tutorial: Mastering Gemini Computer Use: A Comprehensive Hands-On Guide - Build AI agents that control browsers, mobile devices, and desktops with Gemini 3.5 Flash&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;Repository structure&lt;/strong&gt; is shown below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;computer-use-tutorial/
├── README.md ← You are here
├── requirements.txt ← Python dependencies
├── .env.example ← Template for API key
├── 01-hello-screenshot/ ← Step 1: Visual understanding
│ └── hello_screenshot.py
├── 02-single-action/ ← Step 2: One screenshot → one click
│ └── single_action.py
├── 03-browser-agent/ ← Step 3: Full agentic browser loop
│ ├── browser_agent.py
│ └── playwright_env.py
├── 04-mobile-agent/ ← Step 4: Android + Interactions API
│ ├── mobile_agent.py
│ ├── adb_bridge.py
│ └── setup_emulator.sh
├── 05-enterprise-platform/ ← Step 5: Vertex AI + sandboxes
│ └── enterprise_agent.py
└── 06-use-cases/ ← 5 real-world use cases
    ├── usecase1_qa_testing/
    ├── usecase2_price_comparison/
    ├── usecase3_mobile_testing/
    ├── usecase4_web_research/
    └── usecase5_form_filling/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;1. Clone the repository&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;git clone https://github.com/rominirani/computer-use-tutorial
&lt;span class="nb"&gt;cd &lt;/span&gt;computer-use-tutorial
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. Create a Python virtual environment&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;python3 &lt;span class="nt"&gt;-m&lt;/span&gt; venv .venv
&lt;span class="nb"&gt;source&lt;/span&gt; .venv/bin/activate &lt;span class="c"&gt;# macOS / Linux&lt;/span&gt;
&lt;span class="c"&gt;# On Windows: .venv\Scripts\activate&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;⚠️ Important :&lt;/strong&gt; Always activate the virtual environment before running any tutorial script. If your shell prompt doesn’t show (.venv), run source .venv/bin/activate again.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Install Python dependencies&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;pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; requirements.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The requirements.txt is intentionally lean:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;google-genai&amp;gt;=2.7.0
playwright==1.55.0
pydantic&amp;gt;=2.0
rich
termcolor
python-dotenv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;What is Playwright doing here?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;a href="https://playwright.dev/" rel="noopener noreferrer"&gt;Playwright&lt;/a&gt; is the “ &lt;strong&gt;hands&lt;/strong&gt; ” of the agent. Gemini Computer Use gives the model &lt;strong&gt;eyes&lt;/strong&gt; (it can see screenshots) and a &lt;strong&gt;brain&lt;/strong&gt; (it decides what to do), but it has no way to actually interact with a browser. That’s where Playwright comes in.&lt;/p&gt;

&lt;p&gt;It is an open-source browser automation library from Microsoft. It lets Python code control a real Chromium browser i.e. open pages, click at pixel coordinates, type text, scroll, take screenshots, intercept popups, etc.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why we need it?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
The Gemini model returns structured instructions like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;click(x=396, y=185)
type(text="hello world")
scroll(direction="down")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But these are just data. The model can’t execute them. Something needs to translate click(x=396, y=185) into an actual mouse click inside a real browser. Playwright does that:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Model says click(x=396, y=185) → Playwright runs page.mouse.click(506, 148)
Model says type("hello") → Playwright runs page.keyboard.type("hello")
Model says take a screenshot → Playwright runs page.screenshot() → PNG bytes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Could you use something else?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Yes you could. Selenium, Puppeteer, or any browser automation tool would work. Playwright is chosen here because it’s fast, has a clean Python API, handles headless mode well, and has built-in screenshot capture. For mobile, we use ADB instead of Playwright (same role, different “hands”).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Playwright doesn’t use the Chrome/Chromium already on your machine.&lt;/strong&gt; It ships its own browser binaries that are patched for automation, they expose internal APIs (like the Chrome DevTools Protocol) that Playwright uses to control the browser programmatically (click, type, screenshot, navigate, etc.).&lt;/p&gt;

&lt;p&gt;playwright install chromium downloads this patched Chromium binary (~150 MB) into a Playwright-managed directory (e.g. ~/Library/Caches/ms-playwright/).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Install the Chromium browser binary&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;playwright &lt;span class="nb"&gt;install &lt;/span&gt;chromium
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Verify it works:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python3 &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"from playwright.sync_api import sync_playwright; pw = sync_playwright().start(); b = pw.chromium.launch(); print('✅ Playwright Chromium works'); b.close(); pw.stop()"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;5. Configure your Gemini API key&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Please get a Gemini API Key from &lt;a href="https://ai.google.dev/gemini-api/docs/api-key" rel="noopener noreferrer"&gt;here&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;cp&lt;/span&gt; .env.example .env
&lt;span class="c"&gt;# Edit .env and replace 'your-api-key-here' with your actual key&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your .env file should look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="py"&gt;GEMINI_API_KEY&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;AIzaSy...(your actual key)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;6. Verify — run Step 01&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="nb"&gt;cd &lt;/span&gt;01-hello-screenshot
python hello_screenshot.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you see the model describe the Hacker News page, your setup is complete for Steps 1–3 and browser-based use cases. 🎉&lt;/p&gt;

&lt;p&gt;In my case here, this is what I got as output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;✓ Gemini client initialised

============================================================
  Step 1 → Launch browser
  Opening https://news.ycombinator.com
============================================================

  → Page loaded: Hacker News
  → Viewport : 1280×800

============================================================
  Step 2 → Capture screenshot
  Taking a full-viewport PNG snapshot
============================================================

  → Screenshot captured: 206.7 KB
  → Saved to : /Users/romin/computer-use-tutorial/01-hello-screenshot/screenshot.png

============================================================
  Step 3 → Send to Gemini
  Asking the model to describe the screenshot
============================================================

============================================================
  Step 4 → Model response
  Gemini's description of the screenshot
============================================================

Based on the screenshot provided, here is a detailed description of the webpage:

### **Website Name and Identity**
* **Site Name:**  **Hacker News** (a social news website focusing on computer science and entrepreneurship, run by the investment fund Y Combinator).
* **Logo:** A small, bright orange square containing a stylized white letter **"Y"** sits in the top-left corner.

### **Color Scheme**
* **Primary Accent:** Bright safety orange (`#ff6600`), used exclusively for the top navigation bar.
* **Background:** The main content area has a very light, warm gray/off-white background, while the outer margins of the page are plain white.
* **Text:** Dark gray to black for the main headlines, and a lighter, muted gray for metadata (points, time, domains, and comment counts).

### **Layout and Navigation**
* **Structure:** The site features an extremely minimalist, text-heavy, "Web 1.0" style layout. The content is centered in a single vertical column with wide white margins on the left and right.
* **Header Bar:** A solid orange horizontal bar spans the top of the content column. 
    * On the left, next to the "Y" logo, is the bold text **"Hacker News"** followed by a pipe-separated menu of navigation links: `new | past | comments | ask | show | jobs | submit`.
    * On the far right of this bar is a single `login` link.
* **Main List:** Below the header is a sequentially numbered list of stories (numbered 1 through 22 are visible). 

### **Anatomy of a List Item**
Each item in the list follows a strict, consistent format:
1. **Number and Upvote Arrow:** A number (e.g., "1.") followed by a small, light-gray upward-pointing triangle (▲) used for voting.
2. **Headline:** The title of the article, styled as a clickable dark link.
3. **Source Domain:** Directly next to the headline, the hosting website's domain is listed in parentheses in light gray (e.g., `(om.co)` or `(github.com/plbrault)`).
4. **Metadata Line:** Positioned directly below the headline in smaller, lighter text. This includes:
    * The score (e.g., "843 points")
    * The submitting user's handle (e.g., "by minimaxir")
    * How long ago it was posted (e.g., "11 hours ago")
    * A "hide" link
    * The comment count, which links to the discussion page (e.g., "96 comments").

### **Visible Top Headlines**
The top stories visible on this front page cover tech news, programming, hardware, and history. Notable headlines include:
1. *Om Malik has died* (om.co)
2. *Why current LLM costs are not sustainable* (patadia.org)
3. *An entire Herculaneum scroll has been read for the first time* (scrollprize.org)
4. ....
10. ....

────────────────────────────────────────────────────────────
Cleaning up browser resources...
✓ Done — screenshot saved to screenshot.png
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  &lt;strong&gt;(Optional) Android Emulator Setup&lt;/strong&gt;
&lt;/h4&gt;

&lt;blockquote&gt;
&lt;p&gt;Skip this if you only want the browser-based examples (Steps 1–3, Use Cases 1–2, 4–5).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Option A: Use the included setup script&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="nb"&gt;cd &lt;/span&gt;04-mobile-agent
&lt;span class="nb"&gt;chmod&lt;/span&gt; +x setup_emulator.sh
./setup_emulator.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This idempotent script installs Java, Android SDK, creates an AVD named ComputerUseTutorial, and prints the export lines for your shell.&lt;/p&gt;

&lt;p&gt;If you are familiar with Android SDK, feel free to look at the setup_emulator.sh script and create an AVD named ComputerUseTutorial.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Option B: Existing Android SDK&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;# Common ANDROID_HOME locations:&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;ANDROID_HOME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;~/Library/Android/sdk &lt;span class="c"&gt;# Android Studio default&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;ANDROID_HOME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/opt/homebrew/share/android-commandlinetools &lt;span class="c"&gt;# Homebrew (Apple Silicon)&lt;/span&gt;
&lt;span class="c"&gt;# Add to PATH&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$ANDROID_HOME&lt;/span&gt;&lt;span class="s2"&gt;/emulator:&lt;/span&gt;&lt;span class="nv"&gt;$ANDROID_HOME&lt;/span&gt;&lt;span class="s2"&gt;/platform-tools:&lt;/span&gt;&lt;span class="nv"&gt;$PATH&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="c"&gt;# Add to ~/.zshrc so it persists&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'export ANDROID_HOME=~/Library/Android/sdk'&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; ~/.zshrc
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'export PATH="$ANDROID_HOME/emulator:$ANDROID_HOME/platform-tools:$PATH"'&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; ~/.zshrc
&lt;span class="nb"&gt;source&lt;/span&gt; ~/.zshrc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Starting and verifying the emulator&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;# List and start&lt;/span&gt;
emulator &lt;span class="nt"&gt;-list-avds&lt;/span&gt;
emulator &lt;span class="nt"&gt;-avd&lt;/span&gt; &amp;lt;your-avd-name&amp;gt;
&lt;span class="c"&gt;# Verify it's ready&lt;/span&gt;
adb devices &lt;span class="c"&gt;# → emulator-5554 device&lt;/span&gt;
adb shell getprop sys.boot_completed &lt;span class="c"&gt;# → 1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  &lt;strong&gt;(Optional) Google Cloud Setup&lt;/strong&gt;
&lt;/h4&gt;

&lt;blockquote&gt;
&lt;p&gt;Skip this if you don’t have a Google Cloud project or only want the Gemini API.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Authenticate&lt;/span&gt;
gcloud auth login
gcloud auth application-default login
gcloud config &lt;span class="nb"&gt;set &lt;/span&gt;project YOUR_PROJECT_ID
&lt;span class="c"&gt;# Enable Vertex AI API&lt;/span&gt;
gcloud services &lt;span class="nb"&gt;enable &lt;/span&gt;aiplatform.googleapis.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add to your .env:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="py"&gt;GCP_PROJECT_ID&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;your-gcp-project-id&lt;/span&gt;
&lt;span class="py"&gt;GCP_LOCATION&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;us-central1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Required IAM role: roles/aiplatform.user&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gcloud projects add-iam-policy-binding YOUR_PROJECT_ID &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--member&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"user:your-email@domain.com"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--role&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"roles/aiplatform.user"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Understanding the Code: Key Computer Use Patterns
&lt;/h3&gt;

&lt;p&gt;Before diving into the step-by-step code, here are the patterns you’ll see in every script.&lt;/p&gt;

&lt;h4&gt;
  
  
  Pattern 1: Normalized Coordinates (0–999)
&lt;/h4&gt;

&lt;p&gt;The model always outputs coordinates in a 0–999 grid, regardless of screen size. Your code must denormalize:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Model returns: click(x=396, y=185) — these are NOT pixels!
&lt;/span&gt;&lt;span class="n"&gt;pixel_x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;396&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;viewport_width&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# 396 → 506 on a 1280px screen
&lt;/span&gt;&lt;span class="n"&gt;pixel_y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;185&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;viewport_height&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# 185 → 148 on an 800px screen
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the most common source of bugs, forgetting to denormalize will cause clicks to land in the wrong place.&lt;/p&gt;

&lt;h4&gt;
  
  
  Pattern 2: The Agentic Loop
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1. Take screenshot → send to model with task description
2. Model returns: function_call (e.g., click, type, scroll)
3. Execute the action in the browser/device
4. Take a NEW screenshot → send back as FunctionResponse
5. Goto 2 — until model returns plain text (= task complete)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The key insight:&lt;/strong&gt; the model signals it’s done by &lt;strong&gt;returning&lt;/strong&gt;  &lt;strong&gt;text&lt;/strong&gt; instead of &lt;strong&gt;function_calls&lt;/strong&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Pattern 3: FunctionResponse Must Include a Screenshot
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nc"&gt;FunctionResponse&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;click&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="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;result&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;ok&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;screenshot&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;types&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Part&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;from_bytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;screenshot_png&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mime_type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;image/png&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="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Without the screenshot, the model is blind and can’t plan its next move.&lt;/p&gt;

&lt;h4&gt;
  
  
  Pattern 4: Tool Declaration
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&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;types&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Tool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;computer_use&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;ComputerUse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;environment&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="n"&gt;Environment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ENVIRONMENT_BROWSER&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="c1"&gt;# or ENVIRONMENT_MOBILE / ENVIRONMENT_DESKTOP
&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;p&gt;This is NOT a regular function declaration — it activates the model’s built-in understanding of screenshots and UI interaction.&lt;/p&gt;

&lt;h4&gt;
  
  
  Pattern 5: Screenshot Pruning
&lt;/h4&gt;

&lt;p&gt;Screenshots are ~100–300 KB each. In a 20-turn conversation, that’s 2–6 MB of image data in the context:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Keep only the 3 most recent screenshots
&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;old_turn&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;history&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;part&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;old_turn&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="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;hasattr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;part&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;inline_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;part&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;inline_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt; &lt;span class="c1"&gt;# free memory, keep text
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step-by-Step Tutorial
&lt;/h3&gt;

&lt;p&gt;This tutorial has several steps (numbered 1 to 5). Step 1 to 3 can be done simply via Python and Gemini API Key. Step 4 is about Android , while Step 5 is about Google Cloud.&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 1 : Hello Screenshot 01-hello-screenshot/
&lt;/h4&gt;

&lt;p&gt;Before we can build an agent that controls a screen, we need to make sure it can see one. In this step, you’ll launch a headless browser, navigate to Hacker News, capture a screenshot, and send it to Gemini 3.5 Flash to get a visual description. &lt;strong&gt;There’s no Computer Use here ,&lt;/strong&gt; just the two foundational building blocks (screenshots + the model) that every subsequent step builds on.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Concept:&lt;/strong&gt; This step uses &lt;strong&gt;no Computer Use at all&lt;/strong&gt;. It establishes the two foundational building blocks:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Capturing screenshots&lt;/li&gt;
&lt;li&gt;Sending them to Gemini , that every subsequent step depends on.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Code Walkthrough&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;generate_content&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-3.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;contents&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&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;Content&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;role&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&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="p"&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;Part&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Describe what you see...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&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;Part&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                    &lt;span class="n"&gt;inline_data&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;Blob&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                        &lt;span class="n"&gt;mime_type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;image/png&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;screenshot_bytes&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="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;p&gt;The SDK handles base64 encoding. You pass raw bytes and the MIME type.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Running It&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="nb"&gt;cd &lt;/span&gt;01-hello-screenshot
python hello_screenshot.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Expected Output&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;✓ Gemini client initialised
Step 1 → Launch browser
  Opening https://news.ycombinator.com
  → Page loaded: Hacker News
  → Viewport : 1280×800
  Step 4 → Model response
  The screenshot shows Hacker News (news.ycombinator.com)...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Step 2 : Your First Computer Use Action 02-single-action/
&lt;/h4&gt;

&lt;p&gt;Now we give the model its “ &lt;strong&gt;hands&lt;/strong&gt;.” You’ll show Gemini a screenshot of Wikipedia’s language selection page and ask it to click on the English link. The model will return a function_call with normalized coordinates, and you'll translate those into real pixel positions and execute the click with Playwright. This is a single round-trip — one screenshot in, one action out — but it covers the most critical concept in Computer Use: &lt;strong&gt;coordinate normalization.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Concept:&lt;/strong&gt; This is where Computer Use enters the picture. The critical new concept is &lt;strong&gt;coordinate normalization&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%2F6ou1fagkqhpzjnqdj28r.png" class="article-body-image-wrapper"&gt;&lt;img 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%2F6ou1fagkqhpzjnqdj28r.png" width="799" height="201"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Code Walkthrough&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Declare the Computer Use tool
&lt;/span&gt;&lt;span class="n"&gt;computer_use_tool&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;Tool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;computer_use&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;ComputerUse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;environment&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="n"&gt;Environment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ENVIRONMENT_BROWSER&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="c1"&gt;# Send request
&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;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;generate_content&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-3.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;contents&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;request_contents&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;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;computer_use_tool&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# Parse and execute
&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;part&lt;/span&gt; &lt;span class="ow"&gt;in&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;candidates&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="n"&gt;content&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="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;part&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;function_call&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;fc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;part&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;function_call&lt;/span&gt;
&lt;span class="n"&gt;pixel_x&lt;/span&gt; &lt;span class="o"&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;fc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;x&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;SCREEN_WIDTH&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;pixel_y&lt;/span&gt; &lt;span class="o"&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;fc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;y&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;SCREEN_HEIGHT&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mouse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pixel_x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pixel_y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Running It&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="nb"&gt;cd &lt;/span&gt;02-single-action
python single_action.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Expected Output&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;✓ Gemini client initialised

================================================================
  Step 1 → Launch browser
  Navigating to https://www.wikipedia.org
================================================================

  → Page loaded : Wikipedia
  → Current URL : https://www.wikipedia.org/
  → Viewport : 1280×800

================================================================
  Step 2 → Capture screenshot
  Grabbing the Wikipedia portal page
================================================================

  → Screenshot size : 124.7 KB
  → Saved to : /Users/romin/computer-use-tutorial/02-single-action/01_before_click.png

================================================================
  Step 3 → Ask Gemini to click
  Sending screenshot + instruction with Computer Use tool
================================================================

  → Response received from Gemini

================================================================
  Step 4 → Parse response
  Extracting the function call from the model
================================================================

  Function call received:
    Name : click
    x : 396
    intent: Click on the English Wikipedia link to navigate to the English Wikipedia.
    y : 182

================================================================
  Step 5 → Execute click
  Converting coordinates and clicking
================================================================

  Coordinate conversion:
    Normalised : (396, 182) [0-999 space]
    Pixel : (506, 145) [1280×800 viewport]

  → Click executed at pixel (506, 145)
  → Page navigated to: https://www.wikipedia.org/

================================================================
  Step 6 → Verify result
  Taking a post-click screenshot
================================================================

  → Screenshot size : 315.8 KB
  → Saved to : /Users/romin/computer-use-tutorial/02-single-action/02_after_click.png
  → Current URL : https://en.wikipedia.org/wiki/Main_Page
  → Page title : Wikipedia, the free encyclopedia

  ✅ SUCCESS — Navigated to English Wikipedia!

────────────────────────────────────────────────────────────────
Cleaning up browser resources...
✓ Done — screenshots saved to 01_before_click.png &amp;amp; 02_after_click.png
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Step 3 : Building a Full Browser Agent 03-browser-agent/
&lt;/h4&gt;

&lt;p&gt;This is the big leap where we are going from a single action to a fully autonomous agent. You’ll build a complete browser agent that can accept any task (“find the top 3 stories on Hacker News”), take screenshots, send them to the model, execute the returned actions, capture new screenshots, and loop until the task is done. Along the way, you’ll tackle the real-world challenges: managing a growing conversation history, pruning old screenshots to stay within context limits, handling safety decisions, and recovering from transient API errors with exponential backoff.&lt;/p&gt;

&lt;p&gt;Key Concept: This is the big step, going from a single action to a fully autonomous agent.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Critical Pattern: Screenshot Pruning&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_prune_old_screenshots&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="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;screenshots_seen&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;reversed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_history&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;content&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;role&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;content&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="k"&gt;continue&lt;/span&gt;
        &lt;span class="n"&gt;has_screenshot&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;any&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;function_response&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;function_response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parts&lt;/span&gt;
            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;content&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="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;has_screenshot&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;screenshots_seen&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;screenshots_seen&lt;/span&gt; &lt;span class="o"&gt;&amp;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;MAX_SCREENSHOTS_IN_HISTORY&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;part&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;content&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="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;part&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;function_response&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;part&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;function_response&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="n"&gt;part&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;function_response&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="bp"&gt;None&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Critical Pattern: FunctionResponse Construction&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nc"&gt;FunctionResponse&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;fc&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;response&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;url&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;current_url&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="p"&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;FunctionResponsePart&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;inline_data&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;FunctionResponseBlob&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="n"&gt;mime_type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;image/png&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;post_action_png&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="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Running It&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="nb"&gt;cd &lt;/span&gt;03-browser-agent
python browser_agent.py &lt;span class="nt"&gt;--task&lt;/span&gt; &lt;span class="s2"&gt;"Go to https://news.ycombinator.com and tell me the top 3 stories"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Expected Output&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ Gemini Computer Use — Browser Agent │
│ Model: gemini-3.5-flash | Viewport: 1280×800 | Headless: False │
╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
────────────────────────────────────────────────────────── Browser Agent Starting ──────────────────────────────────────────────────────────
Task: Go to https://news.ycombinator.com and tell me the top 3 stories

Initial screenshot captured.

─────────────────────────────────────────────────────────────── Iteration 1 ────────────────────────────────────────────────────────────────
╭───────────────────────────────────────────────────────────── Model Thinking ─────────────────────────────────────────────────────────────╮
│ Okay, here's my thought process on this task: │
│ │
│ **Accessing and Prioritizing Hacker News Articles** │
│ │
│ Right, so the goal is clear: identify the top three stories currently dominating Hacker News. My immediate instinct is to open the site. │
│ It's second nature at this point – navigate to `https://news.ycombinator.com`. Once I'm there, the real work begins. I'll need to sift │
│ through the current submissions, using my knowledge of the site's ranking algorithm and usual trends, to identify which articles are │
│ garnering the most attention. I'll be looking at score, comment count, and potentially the recency of the posts to figure out what's │
│ currently hot and relevant. The top three are what I'm looking for, and I can be flexible with the ranking methodology. │
│ │
│ │
│ │
╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
  ▶ navigate(intent=Navigate to Hacker News, url=https://news.ycombinator.com)
  → Screenshot captured | URL: https://news.ycombinator.com/

─────────────────────────────────────────────────────────────── Iteration 2 ────────────────────────────────────────────────────────────────
╭───────────────────────────────────────────────────────────── Model Thinking ─────────────────────────────────────────────────────────────╮
│ Okay, here's my take on those Hacker News headlines, as I see them: │
│ │
│ **Hacker News Digest - A Quick Glance** │
│ │
│ Alright, let's process these top stories on Hacker News. First up, the Patadia article on LLM costs – always a crucial point for │
│ long-term viability, and something I've been tracking myself. The core of this research is likely to be a deep dive into the │
│ computational inefficiencies, scaling issues, and the sheer energy consumption that underpins current models. I'm especially keen to see │
│ what specific cost-saving strategies the author proposes, and whether they involve architectural improvements, hardware optimization, or │
│ more fundamental algorithmic innovations. That's definitely one to bookmark and dig into. │
│ │
│ Then, a somber note: Om Malik has passed. A prominent voice in the tech sphere is gone. Always a difficult thing to grapple with when a │
│ familiar and respected figure leaves the scene. My thoughts are with his friends and family. A pause for reflection is definitely │
│ warranted. │
│ │
│ Finally, the Herculaneum scroll! This is truly fascinating. Reading an entire scroll from Herculaneum is a significant breakthrough. I'm │
│ guessing the team has leveraged advanced imaging techniques like X-ray tomography and computational tools for deciphering fragmented │
│ texts. What surprises me is this is a first. I'll need to research what the issues have been in deciphering this, if the material has │
│ been too degraded for even cutting-edge processing, or if this new tech is truly groundbreaking. The content itself will undoubtedly │
│ offer invaluable insights into ancient history, philosophy, and everyday life. A promising development. │
│ │
│ │
│ │
╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯

────────────────────────────────────────────────────────────── Task Complete ───────────────────────────────────────────────────────────────

Agent Summary: The top 3 stories on Hacker News are:

1. **Why current LLM costs are not sustainable** (patadia.org)
2. **Om Malik has died** (om.co)
3. **An entire Herculaneum scroll has been read for the first time** (scrollprize.org)

─────────────────────────────────────────────────────────────── Final Result ───────────────────────────────────────────────────────────────

The top 3 stories on Hacker News are:

1. **Why current LLM costs are not sustainable** (patadia.org)
2. **Om Malik has died** (om.co)
3. **An entire Herculaneum scroll has been read for the first time** (scrollprize.org)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Architecture:&lt;/strong&gt; browser_agent.py (AI loop) + playwright_env.py (browser abstraction).&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 4 : Android Mobile Agent 04-mobile-agent/
&lt;/h4&gt;

&lt;p&gt;We swap the browser for a phone. In this step, you’ll connect to an Android emulator via ADB, capture screenshots of the device screen, and let Gemini drive it with touch gestures : taps, swipes, and long-presses. This step also introduces the Interactions API, a stateful alternative to generateContent where the server manages conversation history for you. Instead of sending the full history every turn, you just chain calls with previous_interaction_id , thereby making the code simpler.&lt;/p&gt;

&lt;h4&gt;
  
  
  Interactions API vs generateContent
&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%2F7r25qj42trsly5sl7kps.png" class="article-body-image-wrapper"&gt;&lt;img 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%2F7r25qj42trsly5sl7kps.png" width="800" height="286"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  ADB Bridge Pattern
&lt;/h4&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;click&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&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;x&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;**&lt;/span&gt;&lt;span class="n"&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="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;px&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;py&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="nf"&gt;_denormalize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&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="nf"&gt;_execute&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;shell&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;input&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;tap&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;px&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;py&lt;/span&gt;&lt;span class="p"&gt;)])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Running It
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Start emulator first (see Android Setup above)&lt;/span&gt;
&lt;span class="nb"&gt;cd &lt;/span&gt;04-mobile-agent
python mobile_agent.py &lt;span class="s2"&gt;"Open Settings and check the Android version"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Expected Output
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;╔══════════════════════════════════════════════════════════╗
║ Gemini Computer Use — Android Mobile Agent ║
║ Model: gemini-3.5-flash | API: Interactions ║
╚══════════════════════════════════════════════════════════╝
Turn 1/50
  🔧 Action: open_app({'package_name': 'com.android.settings'})
  ✓ Result: {'status': 'ok'}
  ... (4-6 turns: scrolls, clicks About Phone, reads version) ...
✅ Agent completed the task!
   Model response: The Android version is 16.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Step 5 : Enterprise Platform 05-enterprise-platform/
&lt;/h4&gt;

&lt;p&gt;Everything you’ve built so far works with a free Gemini API key. But when you’re ready for production i.e. IAM authentication, VPC isolation, audit logging, and managed browser sandboxes, you can move to Vertex AI. The best part? The agent code is virtually identical. You change one line to switch from API-key auth to IAM, and optionally connect to a cloud-hosted sandbox browser instead of launching a local one. This step walks through both approaches.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The One-Line Migration&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Your agent code — the agentic loop, the action dispatch, the screenshot pruning — is 100% identical between Gemini API and Vertex AI. The only change:&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%2Feqe05owfitis89hqb0yy.png" class="article-body-image-wrapper"&gt;&lt;img 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%2Feqe05owfitis89hqb0yy.png" width="800" height="232"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CDP Sandbox Connection&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Local browser (Steps 1-3):
&lt;/span&gt;&lt;span class="n"&gt;browser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pw&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chromium&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;launch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;headless&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="c1"&gt;# Managed sandbox (Step 5):
&lt;/span&gt;&lt;span class="n"&gt;browser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pw&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chromium&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect_over_cdp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cdp_endpoint&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Running It
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;05-enterprise-platform
&lt;span class="c"&gt;# Approach 1: Self-managed browser (your local Playwright)&lt;/span&gt;
python enterprise_agent.py &lt;span class="nt"&gt;--approach&lt;/span&gt; self-managed &lt;span class="nt"&gt;--project&lt;/span&gt; YOUR_PROJECT_ID
&lt;span class="c"&gt;# Approach 2: Managed sandbox (cloud-hosted browser)&lt;/span&gt;
python enterprise_agent.py &lt;span class="nt"&gt;--approach&lt;/span&gt; managed-sandbox &lt;span class="nt"&gt;--project&lt;/span&gt; YOUR_PROJECT_ID
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;💡 Tip : Replace YOUR_PROJECT_ID with your actual Google Cloud project ID. You can also set it in .env as GCP_PROJECT_ID=my-company-prod-123.&lt;/p&gt;

&lt;h3&gt;
  
  
  Part 5: Real-World Use Cases
&lt;/h3&gt;

&lt;p&gt;Each use case in 06-use-cases/ is a complete, self-contained script demonstrating a practical application.&lt;/p&gt;

&lt;h3&gt;
  
  
  Use Case 1: QA Testing (TodoMVC)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Scenario&lt;/strong&gt; : Run end-to-end QA tests on a React web app without writing fragile selectors. The agent &lt;strong&gt;sees&lt;/strong&gt; the app and tests it the way a human QA tester would.&lt;/p&gt;

&lt;p&gt;Architecture: generateContent API with a full agentic loop + custom report_qa_result function (multi-tool composition).&lt;/p&gt;

&lt;h4&gt;
  
  
  The Prompt
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Navigate to https://todomvc.com/examples/react/dist/ and perform QA testing:
1. Add three todos: &lt;span class="s1"&gt;'Buy groceries'&lt;/span&gt;, &lt;span class="s1"&gt;'Read a book'&lt;/span&gt;, &lt;span class="s1"&gt;'Write code'&lt;/span&gt;
2. Mark &lt;span class="s1"&gt;'Read a book'&lt;/span&gt; as &lt;span class="nb"&gt;complete
&lt;/span&gt;3. Verify items are displayed correctly
4. Click the &lt;span class="s1"&gt;'Completed'&lt;/span&gt; filter
5. Report what you see
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Running It
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd 06-use-cases/usecase1_qa_testing
python qa_agent.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Step-by-Step Walkthrough
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Agent navigates to TodoMVC React app&lt;/li&gt;
&lt;li&gt;Clicks “What needs to be done?” input and types “Buy groceries” + Enter&lt;/li&gt;
&lt;li&gt;Repeats for “Read a book” and “Write code”&lt;/li&gt;
&lt;li&gt;Clicks the circle next to “Read a book” to mark it complete&lt;/li&gt;
&lt;li&gt;Verifies all three items are visible with correct state&lt;/li&gt;
&lt;li&gt;Clicks the “Completed” filter&lt;/li&gt;
&lt;li&gt;Confirms only “Read a book” appears with strikethrough&lt;/li&gt;
&lt;li&gt;Returns a structured test report&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Expected Results
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;╔══════════════════════════════════════════════════════════════╗
║ Use Case 1: Automated QA Testing Agent — TodoMVC ║
╚══════════════════════════════════════════════════════════════╝

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  Step 1 → Validate environment
  Checking GEMINI_API_KEY
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  ✓ API key found

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  Step 2 → Launch browser
  Opening https://todomvc.com/examples/react/dist/
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  ✓ Browser launched — viewport &lt;span class="o"&gt;(&lt;/span&gt;1440, 900&lt;span class="o"&gt;)&lt;/span&gt;
  ✓ Page loaded: https://todomvc.com/examples/react/dist/
  ✓ Initial screenshot: 87 KB

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  Step 3 → Initialise QA agent
  Setting up Gemini Computer Use loop
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  ✓ Agent ready — initial screenshot attached to prompt

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  Step 4 → Run QA &lt;span class="nb"&gt;test &lt;/span&gt;plan
  Agent is now autonomously executing tests…
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

────────────────────────────────────────────────────────────────
  🤖 Agent Turn 1
────────────────────────────────────────────────────────────────
Tools at indices &lt;span class="o"&gt;[&lt;/span&gt;1] are not compatible with automatic &lt;span class="k"&gt;function &lt;/span&gt;calling &lt;span class="o"&gt;(&lt;/span&gt;AFC&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt; AFC is disabled. If AFC is intended, please include python callables &lt;span class="k"&gt;in &lt;/span&gt;the tool list, and &lt;span class="k"&gt;do &lt;/span&gt;not include &lt;span class="k"&gt;function &lt;/span&gt;declaration and MCP server &lt;span class="k"&gt;in &lt;/span&gt;the tool list.
  💭 Reasoning: &lt;span class="k"&gt;**&lt;/span&gt;QA Test Plan: TodoMVC React Application - Add Todo Items&lt;span class="k"&gt;**&lt;/span&gt;

Okay, &lt;span class="nb"&gt;let&lt;/span&gt;&lt;span class="s1"&gt;'s get down to brass tacks. I need to run a QA test plan on this TodoMVC React application. The first test is pretty straightforw…
  ▶ Action: click(x=603, y=180, intent=Click the todo input field to focus it.)
     📸 Screenshot captured (87 KB) — URL: https://todomvc.com/examples/react/dist/

────────────────────────────────────────────────────────────────
  🤖 Agent Turn 2
────────────────────────────────────────────────────────────────
Tools at indices [1] are not compatible with automatic function calling (AFC). AFC is disabled. If AFC is intended, please include python callables in the tool list, and do not include function declaration and MCP server in the tool list.
  💭 Reasoning: Here'&lt;/span&gt;s my attempt at summarizing the thought process, tailored &lt;span class="k"&gt;for &lt;/span&gt;an expert audience:

&lt;span class="k"&gt;**&lt;/span&gt;Initiating Task Execution&lt;span class="k"&gt;**&lt;/span&gt;

Okay, so the prompt is straightforward. It&lt;span class="s1"&gt;'s an instruction set. It'&lt;/span&gt;s not asking …
  ▶ Action: &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;intent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Type &lt;span class="s1"&gt;'Buy groceries'&lt;/span&gt; and press Enter., &lt;span class="nv"&gt;press_enter&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;True, &lt;span class="nv"&gt;text&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Buy groceries&lt;span class="o"&gt;)&lt;/span&gt;
     📸 Screenshot captured &lt;span class="o"&gt;(&lt;/span&gt;94 KB&lt;span class="o"&gt;)&lt;/span&gt; — URL: https://todomvc.com/examples/react/dist/

────────────────────────────────────────────────────────────────
  🤖 Agent Turn 3
────────────────────────────────────────────────────────────────
Tools at indices &lt;span class="o"&gt;[&lt;/span&gt;1] are not compatible with automatic &lt;span class="k"&gt;function &lt;/span&gt;calling &lt;span class="o"&gt;(&lt;/span&gt;AFC&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt; AFC is disabled. If AFC is intended, please include python callables &lt;span class="k"&gt;in &lt;/span&gt;the tool list, and &lt;span class="k"&gt;do &lt;/span&gt;not include &lt;span class="k"&gt;function &lt;/span&gt;declaration and MCP server &lt;span class="k"&gt;in &lt;/span&gt;the tool list.
  💭 Reasoning: Here&lt;span class="s1"&gt;'s my attempt at summarizing the thought process, tailored for an expert audience:

**Initiating a Simple Instruction**

Okay, so the prompt is incredibly straightforward, almost rudimentary. It'&lt;/span&gt;s…
  ▶ Action: &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;text&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Read a book, &lt;span class="nv"&gt;intent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Type &lt;span class="s1"&gt;'Read a book'&lt;/span&gt; and press Enter., &lt;span class="nv"&gt;press_enter&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;True&lt;span class="o"&gt;)&lt;/span&gt;
     📸 Screenshot captured &lt;span class="o"&gt;(&lt;/span&gt;98 KB&lt;span class="o"&gt;)&lt;/span&gt; — URL: https://todomvc.com/examples/react/dist/

────────────────────────────────────────────────────────────────
  🤖 Agent Turn 4
────────────────────────────────────────────────────────────────
Tools at indices &lt;span class="o"&gt;[&lt;/span&gt;1] are not compatible with automatic &lt;span class="k"&gt;function &lt;/span&gt;calling &lt;span class="o"&gt;(&lt;/span&gt;AFC&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt; AFC is disabled. If AFC is intended, please include python callables &lt;span class="k"&gt;in &lt;/span&gt;the tool list, and &lt;span class="k"&gt;do &lt;/span&gt;not include &lt;span class="k"&gt;function &lt;/span&gt;declaration and MCP server &lt;span class="k"&gt;in &lt;/span&gt;the tool list.
  💭 Reasoning: Here&lt;span class="s1"&gt;'s my attempt at summarizing the thought process, tailored for an expert audience:

**Initiating the Inquiry into Gemini'&lt;/span&gt;s Capabilities&lt;span class="k"&gt;**&lt;/span&gt;

Okay, so the prompt directs me to explore the &lt;span class="s2"&gt;"Learn Gemi…
  ▶ Action: type(intent=Type 'Learn Gemini Computer Use' and press Enter., text=Learn Gemini Computer Use, press_enter=True)
     📸 Screenshot captured (103 KB) — URL: https://todomvc.com/examples/react/dist/

────────────────────────────────────────────────────────────────
  🤖 Agent Turn 5
────────────────────────────────────────────────────────────────
Tools at indices [1] are not compatible with automatic function calling (AFC). AFC is disabled. If AFC is intended, please include python callables in the tool list, and do not include function declaration and MCP server in the tool list.
  💭 Reasoning: Okay, here's my understanding, formatted as requested:

**Assessing Task Completion**

Right, let's just make absolutely sure we've got a handle on this. The task asks me to verify the presence of thr…
  ▶ Action: report_qa_result(test_name=Add Todo Items, details=Successfully added 'Buy groceries', 'Read a book', and 'Learn Gemini Computer Use' to the todo list., passed=True)

  📋 QA Result: Add Todo Items → [PASS ✅]
     Details : Successfully added 'Buy groceries', 'Read a book', and 'Learn Gemini Computer Use' to the todo list.

────────────────────────────────────────────────────────────────
  🤖 Agent Turn 6
────────────────────────────────────────────────────────────────
Tools at indices [1] are not compatible with automatic function calling (AFC). AFC is disabled. If AFC is intended, please include python callables in the tool list, and do not include function declaration and MCP server in the tool list.
  💭 Reasoning: **Marking an Item as Complete**

Okay, so the next test is to mark an item as complete. Specifically, I need to find the "&lt;/span&gt;Read a book&lt;span class="s2"&gt;" task and visually confirm that it's marked as done after I intera…
  ▶ Action: click(y=316, intent=Click the toggle checkbox next to 'Read a book'., x=429)
     📸 Screenshot captured (105 KB) — URL: https://todomvc.com/examples/react/dist/

────────────────────────────────────────────────────────────────
  🤖 Agent Turn 7
────────────────────────────────────────────────────────────────
Tools at indices [1] are not compatible with automatic function calling (AFC). AFC is disabled. If AFC is intended, please include python callables in the tool list, and do not include function declaration and MCP server in the tool list.
  💭 Reasoning: Okay, here's my interpretation of that thought process, assuming I'm an expert in this particular task:

**Test Result Reporting - Iteration Complete**

Alright, that's done. I see "&lt;/span&gt;Read a book&lt;span class="s2"&gt;" is cr…
  ▶ Action: report_qa_result(test_name=Mark Complete, passed=True, details=Successfully marked 'Read a book' as completed, showing a strikethrough style and checked state.)

  📋 QA Result: Mark Complete → [PASS ✅]
     Details : Successfully marked 'Read a book' as completed, showing a strikethrough style and checked state.

────────────────────────────────────────────────────────────────
  🤖 Agent Turn 8
────────────────────────────────────────────────────────────────
Tools at indices [1] are not compatible with automatic function calling (AFC). AFC is disabled. If AFC is intended, please include python callables in the tool list, and do not include function declaration and MCP server in the tool list.
  💭 Reasoning: **Executing the "&lt;/span&gt;Filter Completed&lt;span class="s2"&gt;" Test**

Okay, test three is up. We're verifying the "&lt;/span&gt;Completed&lt;span class="s2"&gt;" filter function. Let's start by identifying and clicking the "&lt;/span&gt;Completed&lt;span class="s2"&gt;" filter link at the bottom of…
  ▶ Action: click(intent=Click the 'Completed' filter link., y=438, x=637)
     📸 Screenshot captured (96 KB) — URL: https://todomvc.com/examples/react/dist/#/completed

────────────────────────────────────────────────────────────────
  🤖 Agent Turn 9
────────────────────────────────────────────────────────────────
Tools at indices [1] are not compatible with automatic function calling (AFC). AFC is disabled. If AFC is intended, please include python callables in the tool list, and do not include function declaration and MCP server in the tool list.
  💭 Reasoning: Okay, here's my take on those thoughts, framed as my own reasoning:

**Test Result Verification and Reporting**

Alright, let's just make absolutely sure we're on the right track here. First, I need t…
  ▶ Action: report_qa_result(details=Successfully filtered by 'Completed' and verified that only 'Read a book' is visible in the list., test_name=Filter Completed, passed=True)

  📋 QA Result: Filter Completed → [PASS ✅]
     Details : Successfully filtered by 'Completed' and verified that only 'Read a book' is visible in the list.

────────────────────────────────────────────────────────────────
  🤖 Agent Turn 10
────────────────────────────────────────────────────────────────
Tools at indices [1] are not compatible with automatic function calling (AFC). AFC is disabled. If AFC is intended, please include python callables in the tool list, and do not include function declaration and MCP server in the tool list.

  ✅ Agent finished.
  Final reasoning: Here's your summary:

**QA Session Complete**

Okay, that's it. All three tests have been successfully run and are now complete. Time to formally declare the QA session as finished. I've confirmed all the data, reviewed the results, and I'm satisfied that we can move forward. No outstanding issues or anomalies were discovered. Let's get the final report generated and distributed.

 The QA session is complete. All three tests passed successfully:
1. **Add Todo Items** : Successfully added "&lt;/span&gt;Buy gr…

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  Step 5 → QA Report
  Printing final &lt;span class="nb"&gt;test &lt;/span&gt;results
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

&lt;span class="o"&gt;================================================&lt;/span&gt;
           QA TEST REPORT
&lt;span class="o"&gt;================================================&lt;/span&gt;
  Test: Add Todo Items &lt;span class="o"&gt;[&lt;/span&gt;PASS] ✅
  Test: Mark Complete &lt;span class="o"&gt;[&lt;/span&gt;PASS] ✅
  Test: Filter Completed &lt;span class="o"&gt;[&lt;/span&gt;PASS] ✅
&lt;span class="o"&gt;================================================&lt;/span&gt;
  Overall: 3/3 PASSED
&lt;span class="o"&gt;================================================&lt;/span&gt;

✓ Browser closed. QA session complete.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Key Takeaway:&lt;/strong&gt; Computer Use can replace hundreds of lines of Selenium/Cypress test code with a single natural-language task description.&lt;/p&gt;

&lt;h3&gt;
  
  
  Use Case 2: Price Comparison
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Scenario:&lt;/strong&gt; Compare product prices across the web. The agent searches Google Shopping, extracts prices, and saves them through a custom function, demonstrating multi-tool composition.&lt;/p&gt;

&lt;p&gt;Architecture: Computer Use (for browsing) + custom save_product() function in the same conversation.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;The Prompt&lt;/strong&gt;
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;You are a price comparison agent. Your job is to search for products and
extract pricing information.

## Instructions

1. You are on Amazon.com. In the search box, type "wireless noise
   cancelling headphones" and press Enter to search.

2. Wait for results to load. You should see product listings with names
   and prices.

3. Look at the search results. For each of the top 3-5 products you can
   see, call the `save_product` function with:
   - name: the product name (e.g. "Sony WH-1000XM5")
   - price: the displayed price (e.g. "$278.00")
   - source: "Amazon"

4. If you need to scroll down to see more products, do so.

5. Try to find at least 3 products with visible prices. Save each one
   using `save_product`.

6. After saving 3-5 products, state that the comparison is complete.

IMPORTANT: Call `save_product` once for each product you identify.
Do NOT try to save all products in one call.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Running It
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd 06-use-cases/usecase2_price_comparison
python price_agent.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Expected Results
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;
.... Agent Turn&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt; ...
    🔍 PRICE COMPARISON RESULTS                                
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━┓
┃ Product ┃ Price ┃ Source ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━┩
│ Soundcore by Anker Q20i Hybrid Active Noise │ INR 3,774.86 │ Amazon │
│ Cancelling Headphones, Wireless Over-Ear │ │ │
│ Bluetooth, 40H Long ANC Playtime, Hi-Res Audio, │ │ │
│ Big Bass, Customize via an App, Transparency Mode │ │ │
│ &lt;span class="o"&gt;(&lt;/span&gt;Black&lt;span class="o"&gt;)&lt;/span&gt; │ │ │
├────────────────────────────────────────────────────┼───────────────┼────────────────────┤
│ Sony WH-CH720N Noise Canceling Wireless Headphones │ INR 7,084.34 │ Amazon │
│ Bluetooth Over The Ear Headset with Microphone and │ │ │
│ Alexa Built-in, Black New │ │ │
├────────────────────────────────────────────────────┼───────────────┼────────────────────┤
│ Bose QuietComfort Headphones - Wireless Bluetooth │ INR 16,896.70 │ Amazon │
│ Headphones, Active Over Ear Noise Cancelling and │ │ │
│ Mic, USB-C Charging, Deep Bass, Up to 24 Hours of │ │ │
│ Playtime, Twilight Blue - Limited Edition... │ │ │
├────────────────────────────────────────────────────┼───────────────┼────────────────────┤
│ Bose QuietComfort Headphones - Wireless Bluetooth │ INR 16,896.70 │ Amazon │
│ Headphones, Active Over Ear Noise Cancelling and │ │ │
│ Mic, USB-C Charging, Deep Bass, Up to 24 Hours of │ │ │
│ Playtime, Black │ │ │
└────────────────────────────────────────────────────┴───────────────┴────────────────────┘

  📊 Total products found: 4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Key Takeaway:&lt;/strong&gt; Multi-tool composition is the solid feature. The model seamlessly switches between “driving the browser” and “calling your business logic functions.”&lt;/p&gt;

&lt;h3&gt;
  
  
  Use Case 3: Mobile App Testing
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Scenario&lt;/strong&gt; : Verify that an Android app’s Settings screen works — toggle dark mode, check About Phone, verify system info.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Architecture&lt;/strong&gt; : Uses the Interactions API with ENVIRONMENT_MOBILE.&lt;/p&gt;

&lt;h4&gt;
  
  
  Prompt
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;You are an automated QA agent testing an Android device.

Your current test plan:
1. Open the Android Settings app (package: com.android.settings).
2. Navigate to "Display" settings.
3. Check whether Dark theme / Dark mode is currently ON or OFF.
4. Toggle Dark mode (turn it ON if it is OFF, or OFF if it is ON).
5. Press Back to return to the main Settings screen.
6. Navigate to "About phone" (scroll down if needed).
7. Read the Android version string shown on that page.
8. Report a test summary with: dark mode before, dark mode after, Android version.

Rules:
* Use the tools provided. Scroll down before assuming an item is missing.
* When the task is complete, output a **Test Summary** with all findings.
* Do NOT use the on-screen keyboard — use the `type` tool instead.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Running It
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd 06-use-cases/usecase3_mobile_testing
python app_test_agent.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;⚠️ Prerequisite : You need a running Android emulator. See the Android Setup section above.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Takeaway:&lt;/strong&gt; The Interactions API handles state management server-side, making mobile agents significantly simpler to build.&lt;/p&gt;

&lt;h3&gt;
  
  
  Use Case 4: Web Research &amp;amp; Report
&lt;/h3&gt;

&lt;p&gt;Scenario: Research a topic across multiple websites and produce a structured Markdown report using dual custom functions (save_finding + generate_report).&lt;/p&gt;

&lt;h4&gt;
  
  
  Prompt
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;You are a web research assistant. Your job:

1. The browser is open to DuckDuckGo. Search &lt;span class="k"&gt;for&lt;/span&gt;: &lt;span class="s2"&gt;"{search_query}"&lt;/span&gt;
2. Browse the first 2-3 search result pages.
3. On each page, extract &lt;span class="k"&gt;**&lt;/span&gt;key findings&lt;span class="k"&gt;**&lt;/span&gt; and call the &lt;span class="sb"&gt;``&lt;/span&gt;save_finding&lt;span class="sb"&gt;``&lt;/span&gt; tool
   &lt;span class="k"&gt;for &lt;/span&gt;each distinct insight &lt;span class="o"&gt;(&lt;/span&gt;with a descriptive title, the page URL, the
   key point, and a category like &lt;span class="s2"&gt;"hardware"&lt;/span&gt;, &lt;span class="s2"&gt;"algorithm"&lt;/span&gt;, &lt;span class="s2"&gt;"partnership"&lt;/span&gt;,
   &lt;span class="s2"&gt;"investment"&lt;/span&gt;, or &lt;span class="s2"&gt;"breakthrough"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
4. After collecting findings from 2-3 pages, call &lt;span class="sb"&gt;``&lt;/span&gt;generate_report&lt;span class="sb"&gt;``&lt;/span&gt; to
   signal you are &lt;span class="k"&gt;done&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
5. Finally, output a brief natural-language summary.

Rules:
&lt;span class="k"&gt;*&lt;/span&gt; You MUST call &lt;span class="sb"&gt;``&lt;/span&gt;save_finding&lt;span class="sb"&gt;``&lt;/span&gt; at least once per page visited.
&lt;span class="k"&gt;*&lt;/span&gt; Call &lt;span class="sb"&gt;``&lt;/span&gt;generate_report&lt;span class="sb"&gt;``&lt;/span&gt; exactly once when finished.
&lt;span class="k"&gt;*&lt;/span&gt; Navigate with clicks and scrolls — &lt;span class="nb"&gt;read &lt;/span&gt;the page content on screen.
&lt;span class="k"&gt;*&lt;/span&gt; If a page fails to load, use the browser back button and try the next result.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Running It
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd 06-use-cases/usecase4_web_research
python research_agent.py
# Or with a custom topic:
python research_agent.py --search "AI safety regulations 2026"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Expected Results
&lt;/h4&gt;

&lt;p&gt;A research_report.md file saved to disk with structured findings, source URLs, and a summary.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;✓ Report saved to: /Users/romin/computer-use-tutorial/06-use-cases/usecase4_web_research/report_AI_safety_regulations_2026_2026-06-26_152011.md

                                                               Collected Findings &lt;span class="o"&gt;(&lt;/span&gt;7&lt;span class="o"&gt;)&lt;/span&gt;                                                               
╭─────┬──────────────────────────────────────────────────────────────┬─────────────┬───────────────────────────────────────────────────────────────╮
│ &lt;span class="c"&gt;# │ Title │ Category │ Source │&lt;/span&gt;
├─────┼──────────────────────────────────────────────────────────────┼─────────────┼───────────────────────────────────────────────────────────────┤
│ 1 │ EU AI Act High-Risk AI System Compliance and Penalties │ algorithm │ https://is4.ai/blog/our-blog-1/ai-safety-legislation-2026-gl… │
├─────┼──────────────────────────────────────────────────────────────┼─────────────┼───────────────────────────────────────────────────────────────┤
│ 2 │ California SB 1047 Large-Scale AI Model Safety Protocols │ algorithm │ https://is4.ai/blog/our-blog-1/ai-safety-legislation-2026-gl… │
├─────┼──────────────────────────────────────────────────────────────┼─────────────┼───────────────────────────────────────────────────────────────┤
│ 3 │ China Generative AI Content and Alignment Regulations │ algorithm │ https://is4.ai/blog/our-blog-1/ai-safety-legislation-2026-gl… │
├─────┼──────────────────────────────────────────────────────────────┼─────────────┼───────────────────────────────────────────────────────────────┤
│ 4 │ NIST Launches Autonomous AI Agent Standards Initiative │ algorithm │ https://www.hungyichen.com/en/insights/ai-governance-regulat… │
├─────┼──────────────────────────────────────────────────────────────┼─────────────┼───────────────────────────────────────────────────────────────┤
│ 5 │ Singapore IMDA Model AI Governance Framework &lt;span class="k"&gt;for &lt;/span&gt;Agentic AI │ algorithm │ https://www.hungyichen.com/en/insights/ai-governance-regulat… │
├─────┼──────────────────────────────────────────────────────────────┼─────────────┼───────────────────────────────────────────────────────────────┤
│ 6 │ US Federal AI Litigation Task Force Challenges State AI Laws │ algorithm │ https://www.gunder.com/en/news-insights/insights/2026-ai-law… │
├─────┼──────────────────────────────────────────────────────────────┼─────────────┼───────────────────────────────────────────────────────────────┤
│ 7 │ US Restricts BEAD Funding &lt;span class="k"&gt;for &lt;/span&gt;States with Onerous AI Laws │ partnership │ https://www.gunder.com/en/news-insights/insights/2026-ai-law… │
╰─────┴──────────────────────────────────────────────────────────────┴─────────────┴───────────────────────────────────────────────────────────────╯

✓ Done — report at: /Users/romin/computer-use-tutorial/06-use-cases/usecase4_web_research/report_AI_safety_regulations_2026_2026-06-26_152011.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Key Takeaway:&lt;/strong&gt; Computer Use + custom functions turns Gemini into a &lt;em&gt;research agent&lt;/em&gt; that can navigate the open web and produce structured, citable output.&lt;/p&gt;

&lt;h3&gt;
  
  
  Use Case 5: Form Filling
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Scenario&lt;/strong&gt; : Fill out a complex HTML form with text inputs, radio buttons, checkboxes, dropdowns, and text areas. A classic RPA task.&lt;/p&gt;

&lt;h4&gt;
  
  
  The Prompt
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Fill out the local practice registration form with:
- Name: Jane Smith
- Email: jane.smith@example.com
- Gender: Female
- Mobile: 555-0123
- Subject: Computer Science
- Hobby: Reading
- Address: 123 AI Street, Tech City, CA 90210
- State: California, City: San Francisco

Then submit the form and verify the confirmation.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Running It
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd 06-use-cases/usecase5_form_filling
python form_agent.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The form getting filled in real-time:&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%2Fsesrszop3lzpsfueulr7.png" class="article-body-image-wrapper"&gt;&lt;img 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%2Fsesrszop3lzpsfueulr7.png" width="800" height="337"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Expected Results&lt;/strong&gt;
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;╭───────────────────────────────────────────────────────────────────────────────────── Agent Report ──────────────────────────────────────────────────────────────────────────────────────╮
│ Okay, here&lt;span class="s1"&gt;'s my take on those thoughts, tailored for an expert'&lt;/span&gt;s perspective: │
│ │
│ &lt;span class="k"&gt;**&lt;/span&gt;Registration Confirmation and Report Preparation&lt;span class="k"&gt;**&lt;/span&gt; │
│ │
│ Alright, the registration&lt;span class="s1"&gt;'s gone through. Got the confirmation message – "Registration Submitted Successfully!" – so that'&lt;/span&gt;s a good starting point. Now, &lt;span class="nb"&gt;let&lt;/span&gt;&lt;span class="s1"&gt;'s nail down what needs to │
│ be in this final report. I need to clearly articulate what specific fields were populated correctly, essentially a field-by-field breakdown to demonstrate data integrity. Of course, │
│ the form submission success is key, and I’ll confirm that the confirmation message, the visual indicator of a successful transaction, was present. Time to outline this response. │
│ │
│ │
│ I have successfully completed the form-filling task! │
│ │
│ ### 1. Fields Successfully Filled: │
│ * **First Name** : Jane │
│ * **Last Name** : Smith │
│ * **Email** : jane.smith@example.com │
│ * **Gender** : Female │
│ * **Mobile** : 555-0123 │
│ * **Date of Birth** : 1995-06-15 │
│ * **Subject** : Computer Science │
│ * **Hobbies** : Reading │
│ * **Current Address** : 123 AI Street, Tech City, CA 90210 │
│ * **State** : California │
│ * **City** : San Francisco │
│ │
│ ### 2. Submission Status: │
│ * **Successfully Submitted** : Yes, the form was submitted successfully, and the green confirmation box with **"Registration Submitted Successfully!"** appeared on the screen, │
│ displaying all the correct values. │
╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯

✓ Browser closed
                                                                                   Form Filling Summary                                                                                    

  Metric Value                                                                                                                                                                      
 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 
  Target URL file:///Users/romin/computer-use-tutorial/06-use-cases/usecase5_form_filling/practice_form.html                                                                            

  Total turns 39                                                                                                                                                                         

  Model gemini-3.5-flash                                                                                                                                                           

  API generateContent (browser)                                                                                                                                                  

  Data filled First Name: Jane, Last Name: Smith, Email: jane.smith@example.com, Gender: Female, Mobile: 555-0123, Subject: Computer Science, Hobbies: Reading, Address: 123 AI Street,  
                Tech City, CA 90210, State: California, City: San Francisco

✓ Form filling complete.
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Key Takeaway:&lt;/strong&gt; Computer Use handles diverse HTML controls (radio buttons, checkboxes, dropdowns) that would each require different selector strategies in traditional automation. The model just &lt;em&gt;sees&lt;/em&gt; the form and fills it in.&lt;/p&gt;

&lt;h3&gt;
  
  
  Summary
&lt;/h3&gt;

&lt;p&gt;Gemini Computer Use represents a fundamental shift in how we automate software i.e. from brittle, selector-based scripts to AI agents that &lt;strong&gt;see&lt;/strong&gt; and &lt;strong&gt;interact&lt;/strong&gt; with screens just like humans do. In this tutorial, you went from sending a single screenshot to building autonomous agents that control browsers, drive Android devices, and scale to enterprise with Vertex AI — all powered by the same model and the same Brain → Eyes → Hands architecture.&lt;/p&gt;

&lt;p&gt;The five use cases showed that this isn't a toy demo: QA testing, price comparison, mobile automation, web research, and form filling are real workflows being automated today.&lt;/p&gt;

&lt;p&gt;The code is open, the patterns are reusable, and with gemini-3.5-flash, you're one API call away from giving your next application the ability to operate any screen. Go for it.&lt;/p&gt;




</description>
      <category>gemini</category>
      <category>googleai</category>
      <category>google</category>
      <category>computeruse</category>
    </item>
    <item>
      <title>[Boost]</title>
      <dc:creator>Romin Irani</dc:creator>
      <pubDate>Fri, 12 Jun 2026 14:40:25 +0000</pubDate>
      <link>https://dev.to/iromin/-26ea</link>
      <guid>https://dev.to/iromin/-26ea</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/gde/connecting-gcp-budget-alerts-to-appsheet-a-step-by-step-guide-4pda" class="crayons-story__hidden-navigation-link"&gt;Connecting GCP Budget Alerts to AppSheet: A Step-by-Step Guide&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;
          &lt;a class="crayons-logo crayons-logo--l" href="/gde"&gt;
            &lt;img alt="Google Developer Experts logo" 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%2Forganization%2Fprofile_image%2F11939%2Fe3080d5b-ecde-42a8-b089-bafecc31fa97.png" class="crayons-logo__image" width="800" height="800"&gt;
          &lt;/a&gt;

          &lt;a href="/aryanirani123" class="crayons-avatar  crayons-avatar--s absolute -right-2 -bottom-2 border-solid border-2 border-base-inverted  "&gt;
            &lt;img 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%2Fuser%2Fprofile_image%2F754479%2F1d1fdf42-b44b-4b4b-beba-7125aa2a60e7.jpeg" alt="aryanirani123 profile" class="crayons-avatar__image" width="800" height="533"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/aryanirani123" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Aryan Irani
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Aryan Irani
                
              
              &lt;div id="story-author-preview-content-3883295" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/aryanirani123" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img 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%2Fuser%2Fprofile_image%2F754479%2F1d1fdf42-b44b-4b4b-beba-7125aa2a60e7.jpeg" class="crayons-avatar__image" alt="" width="800" height="533"&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Aryan Irani&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

            &lt;span&gt;
              &lt;span class="crayons-story__tertiary fw-normal"&gt; for &lt;/span&gt;&lt;a href="/gde" class="crayons-story__secondary fw-medium"&gt;Google Developer Experts&lt;/a&gt;
            &lt;/span&gt;
          &lt;/div&gt;
          &lt;a href="https://dev.to/gde/connecting-gcp-budget-alerts-to-appsheet-a-step-by-step-guide-4pda" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Jun 12&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/gde/connecting-gcp-budget-alerts-to-appsheet-a-step-by-step-guide-4pda" id="article-link-3883295"&gt;
          Connecting GCP Budget Alerts to AppSheet: A Step-by-Step Guide
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/googlecloud"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;googlecloud&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/appsheet"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;appsheet&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/finops"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;finops&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/cloudbilling"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;cloudbilling&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/gde/connecting-gcp-budget-alerts-to-appsheet-a-step-by-step-guide-4pda" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/fire-f60e7a582391810302117f987b22a8ef04a2fe0df7e3258a5f49332df1cec71e.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;1&lt;span class="hidden s:inline"&gt;&amp;nbsp;reaction&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/gde/connecting-gcp-budget-alerts-to-appsheet-a-step-by-step-guide-4pda#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              &lt;span class="hidden s:inline"&gt;Add&amp;nbsp;Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            7 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial crayons-icon c-btn__icon"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success crayons-icon c-btn__icon"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
    </item>
    <item>
      <title>Antigravity Managed Agents Tutorial: Ship Production AI Agents</title>
      <dc:creator>Romin Irani</dc:creator>
      <pubDate>Tue, 09 Jun 2026 12:16:25 +0000</pubDate>
      <link>https://dev.to/googleai/antigravity-managed-agents-tutorial-ship-production-ai-agents-21c0</link>
      <guid>https://dev.to/googleai/antigravity-managed-agents-tutorial-ship-production-ai-agents-21c0</guid>
      <description>&lt;p&gt;If you’ve tried building AI applications, you often face a familiar engineering wall.&lt;/p&gt;

&lt;p&gt;It goes like this: You ask a Large Language Model to help you launch a website. It replies with beautiful code. But then what? The AI can’t actually open a text editor, save the file, or click “Run” to see if it works. You need to do all the heavy lifting.&lt;/p&gt;

&lt;p&gt;You might say that you use one of the AI Agents that does a lot more including starting up the server, doing a few tests, etc. Of course they do but in case you had to do that, there are multiple things to consider:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ensure that you do have a sandbox so the AI can run code safely without accidentally wiping your files.&lt;/li&gt;
&lt;li&gt;Stitch together some logic of passing data back and forth across modules.&lt;/li&gt;
&lt;li&gt;You need to configure tools, so that the AI can invoke those tools, talk to your data and/or even run a script.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There’s a lot more to think of and it all points towards more operational and management overheard to keep things running safely.&lt;/p&gt;

&lt;p&gt;Here’s what this looks like in practice. Say you want an AI to write and &lt;em&gt;test&lt;/em&gt; a Python script:&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;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;import&lt;/span&gt; &lt;span class="n"&gt;subprocess&lt;/span&gt;

&lt;span class="n"&gt;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="c1"&gt;# Step 1: Ask the model for code
&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;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;generate_content&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;contents&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Write a Python script that checks password strength and saves a report.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Step 2: YOU must manually extract the code block from the text response
&lt;/span&gt;&lt;span class="n"&gt;code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;extract_code_from_markdown&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;span class="c1"&gt;# You wrote this function
&lt;/span&gt;
&lt;span class="c1"&gt;# Step 3: YOU must save the file and run it locally
&lt;/span&gt;&lt;span class="k"&gt;with&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;password_checker.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;w&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="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# ⚠️ Danger: Running untrusted AI-generated code on YOUR machine!
&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;python3&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;password_checker.py&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;capture_output&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;text&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="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stdout&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You’re doing all the work. The extraction. The file I/O. The risky local execution. The error loop when it inevitably fails.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What if you could replace all of this with a single API call?&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  What Are Managed Agents?
&lt;/h3&gt;

&lt;p&gt;Google’s &lt;strong&gt;Managed Agents&lt;/strong&gt; framework, featuring the flagship &lt;strong&gt;Antigravity&lt;/strong&gt; agent, looks to help you overcome the engineering wall, that we just mentioned.&lt;/p&gt;

&lt;p&gt;Think of it as &lt;strong&gt;Agent-as-a-Service&lt;/strong&gt;. Instead of just giving you a text-based chatbot, Google instantly hands your AI its own secure, fully managed cloud computer (a Linux workspace) with the keys to the live internet.&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%2Fes646druifsk2owm2v3e.png" class="article-body-image-wrapper"&gt;&lt;img 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%2Fes646druifsk2owm2v3e.png" width="800" height="447"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Generated by NotebookLM for this article.&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  The Three Levels of AI Systems
&lt;/h3&gt;

&lt;p&gt;Let’s look at the following table that highlights the three levels of AI Systems:&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%2Fz8q00561vvtul5233bhu.png" class="article-body-image-wrapper"&gt;&lt;img 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%2Fz8q00561vvtul5233bhu.png" width="800" height="334"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  The Core Agentic Loop
&lt;/h3&gt;

&lt;p&gt;When you give an Antigravity Agent a task, it doesn’t just guess an answer. It operates inside a continuous, hardware-backed loop:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌────────────────────────────────────────┐
│ 1. PLAN &amp;amp; REASON │
│ (Analyzes objective &amp;amp; breaks it down) │
└───────────────────┬────────────────────┘
                    │
                    ▼
┌────────────────────────────────────────┐
│ 2. ACT │
│ (Executes a tool: Bash, Python, Web) │
└───────────────────┬────────────────────┘
                    │
                    ▼
┌────────────────────────────────────────┐
│ 3. OBSERVE │
│ (Reads execution output, errors, data) │
└───────────────────┬────────────────────┘
                    │
                    └─── Loop back until task is complete
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This isn’t a one-shot prompt/response. The agent iterates. It writes a script, runs it, reads a SyntaxError from the terminal, fixes the bug, re-runs, and keeps going until the task is done.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Remote Sandbox
&lt;/h3&gt;

&lt;p&gt;Every time you invoke an Antigravity Agent, Google boots up a dedicated workspace:&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%2F9muvn8o4ph82gdbak343.png" class="article-body-image-wrapper"&gt;&lt;img 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%2F9muvn8o4ph82gdbak343.png" width="800" height="290"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What you get is a real Linux computer in the cloud that your agent owns for the duration of its task.&lt;/p&gt;

&lt;h3&gt;
  
  
  Architecture Deep Dive: How It All Works
&lt;/h3&gt;

&lt;p&gt;When working with Managed Agents, you interact with two separate planes via the Gemini API:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                  ┌─────────────────────────────────┐
                  │ YOUR APP │
                  └────────┬───────────────┬────────┘
                           │ │
      1. Define/Configure │ │ 2. Run Task
      (System rules, ID) │ │ (Send Prompt)
                           ▼ ▼
 ┌───────────────────────────────────┐ ┌───────────────────────────────────┐
 │ THE CONTROL PLANE │ │ THE RUNTIME PLANE │
 │ (Agents API) │ │ (Interactions API) │
 ├───────────────────────────────────┤ ├───────────────────────────────────┤
 │ Saves persistent identity, system │ │ Spawns the Ubuntu sandbox, logs │
 │ instructions, and data mounts. │ │ live traces, and processes loops. │
 └───────────────────────────────────┘ └───────────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The Control Plane (Agents API)&lt;/strong&gt; is where you configure and register your agent. Think of it as creating an employee profile i.e. you define its name, system instructions, custom skills, and code repositories to clone. It gives you back a static &lt;strong&gt;Agent ID&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Runtime Plane (Interactions API)&lt;/strong&gt; is where actual work happens. You send a task to your Agent ID via an “Interaction.” This plane handles sandbox provisioning, tool execution, reasoning traces, and the agentic loop.&lt;/p&gt;

&lt;h3&gt;
  
  
  Security: The Egress Proxy
&lt;/h3&gt;

&lt;p&gt;Allowing an autonomous agent to run unverified scripts is a security risk. Google isolates the environment using an &lt;strong&gt;Egress Proxy Layer&lt;/strong&gt; :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; ┌─────────────────────────┐
 │ REMOTE UBUNTU SANDBOX │
 │ (No internal secrets) │
 └───────────┬─────────────┘
             │ Agent attempts outbound API call
             ▼
 ┌─────────────────────────┐
 │ EGRESS PROXY LAYER │ ◄── Checks Domain Allowlist
 ├─────────────────────────┤
 │ Intercepts connection, │
 │ injects secrets securely│
 └───────────┬─────────────┘
             │ Safe, Authenticated Request Sent
             ▼
    [External Target API]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Three key guarantees:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Zero Secrets Inside the Sandbox.&lt;/strong&gt; You never save API keys or database passwords in the agent’s Linux workspace.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Domain Allowlists.&lt;/strong&gt; You explicitly define which external domains the agent can contact.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Header Transformations.&lt;/strong&gt; When the agent needs to call an external API, the Egress Proxy intercepts the request, confirms the domain is allowed, and injects the authentication token automatically. The agent gets the data, but never sees your private key.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Getting Started: Your First Agent in 5 Minutes
&lt;/h3&gt;

&lt;p&gt;Let’s create our First Agent using the Managed Agents framework.&lt;/p&gt;

&lt;h4&gt;
  
  
  Prerequisites
&lt;/h4&gt;

&lt;p&gt;Before writing any code, make sure your environment meets these requirements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Python:&lt;/strong&gt; 3.10+. 3.12 recommended (matches sandbox runtime)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;google-genai SDK&lt;/strong&gt; &amp;gt;=2.0.0. The latest at the time of writing is 2.8.0.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;API Key&lt;/strong&gt; —Free tier available at &lt;a href="https://aistudio.google.com/apikey" rel="noopener noreferrer"&gt;aistudio.google.com/apikey&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OS :&lt;/strong&gt; Any (macOS, Linux, Windows, or WSL). Your code runs locally, the agent runs in Google’s cloud.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python3 &lt;span class="nt"&gt;-m&lt;/span&gt; venv managed-agents-env
&lt;span class="nb"&gt;source &lt;/span&gt;managed-agents-env/bin/activate &lt;span class="c"&gt;# On Windows: managed-agents-env\Scripts\activate&lt;/span&gt;
&lt;span class="c"&gt;# Install (or upgrade) the Google GenAI SDK&lt;/span&gt;
pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-U&lt;/span&gt; google-genai
&lt;span class="c"&gt;# Verify the version — must be 1.14.0 or later&lt;/span&gt;
python3 &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"import google.genai; print(google.genai. __version__ )"&lt;/span&gt;
&lt;span class="c"&gt;# Set your API key (get one at https://aistudio.google.com/apikey)&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;GEMINI_API_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"your-api-key-here"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;No local setup needed?&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;You can also try Managed Agents directly in&lt;/em&gt; &lt;a href="https://aistudio.google.com" rel="noopener noreferrer"&gt;&lt;em&gt;Google AI Studio&lt;/em&gt;&lt;/a&gt; &lt;em&gt;without writing any code. Look for the “Managed Agents” template section. Iit gives you an interactive playground to test agent interactions in your browser.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  Running the Examples
&lt;/h4&gt;

&lt;p&gt;Every code block in this tutorial is a &lt;strong&gt;complete, self-contained Python script&lt;/strong&gt;. To run any example:&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. Save the code to a file (an example name used here is hello_agent.py&lt;/span&gt;
vim hello_agent.py &lt;span class="c"&gt;# or use any editor&lt;/span&gt;

&lt;span class="c"&gt;# 2. Run it&lt;/span&gt;
python3 hello_agent.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;How long does it take?&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;Each interaction takes&lt;/em&gt; &lt;strong&gt;&lt;em&gt;30 seconds to 3 minutes&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;depending on task complexity. The agent is doing real work — booting a sandbox, writing code, executing it, reading errors, and iterating. Simple tasks finish in under a minute; complex multi-turn chains may take 2–3 minutes per turn.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  Your First Interaction: Hello Managed Agents
&lt;/h4&gt;

&lt;p&gt;Remember that painful multi-step code from earlier? Here’s the Antigravity Managed Agents equivalent:&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;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="n"&gt;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="c1"&gt;# One API call. One autonomous agent. One remote Linux sandbox.
&lt;/span&gt;&lt;span class="n"&gt;interaction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;interactions&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;agent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;antigravity-preview-05-2026&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nb"&gt;input&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Write a Python script that generates 100 random exam scores between 0 and 100, &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
          &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;calculates the mean, median, and standard deviation, prints a summary, &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 saves a grade distribution histogram as grade_report.png using matplotlib.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;environment&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;remote&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="c1"&gt;# This provisions a secure Linux sandbox hosted by Google
&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;interaction&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;output_text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Run it:&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;python3 hello_agent.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Expected output&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For the first interaction, it produced the following output (your numbers will vary since the data is random):&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;I&lt;/span&gt; &lt;span class="n"&gt;have&lt;/span&gt; &lt;span class="n"&gt;successfully&lt;/span&gt; &lt;span class="n"&gt;written&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;executed&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;Python&lt;/span&gt; &lt;span class="n"&gt;script&lt;/span&gt; &lt;span class="n"&gt;that&lt;/span&gt; &lt;span class="n"&gt;generates&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt; &lt;span class="n"&gt;random&lt;/span&gt; &lt;span class="n"&gt;exam&lt;/span&gt; &lt;span class="n"&gt;scores&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;computes&lt;/span&gt; &lt;span class="n"&gt;their&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="n"&gt;statistics&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;plots&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;grade&lt;/span&gt; &lt;span class="n"&gt;distribution&lt;/span&gt; &lt;span class="n"&gt;histogram&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;

&lt;span class="c1"&gt;### 1. Generated Python Script (`generate_report.py`)
&lt;/span&gt;
&lt;span class="n"&gt;Here&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;Python&lt;/span&gt; &lt;span class="n"&gt;script&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;which&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;saved&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;environment&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="sb"&gt;`generate_report.py`&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="n"&gt;It&lt;/span&gt; &lt;span class="n"&gt;uses&lt;/span&gt; &lt;span class="sb"&gt;`numpy`&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="n"&gt;generation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sb"&gt;`statistics`&lt;/span&gt; &lt;span class="n"&gt;conventions&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nf"&gt;calculation &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;such&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;sample&lt;/span&gt; &lt;span class="n"&gt;standard&lt;/span&gt; &lt;span class="n"&gt;deviation&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="sb"&gt;`matplotlib`&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;generate&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;high&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;quality&lt;/span&gt; &lt;span class="n"&gt;visualization&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
python&lt;br&gt;
import numpy as np&lt;br&gt;
import matplotlib.pyplot as plt&lt;br&gt;
import statistics&lt;/p&gt;

&lt;p&gt;def generate_and_analyze_grades():&lt;br&gt;
    # Set a random seed for reproducibility&lt;br&gt;
    np.random.seed(42)&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Generate 100 random exam scores between 0 and 100 (inclusive)
scores = np.random.randint(0, 101, size=100)

# Calculate statistics using Python's standard statistics module and NumPy
# (Using ddof=1 for sample standard deviation, which is standard for student grade samples)
mean_val = np.mean(scores)
median_val = np.median(scores)
std_val = np.std(scores, ddof=1)

# Print summary to console
print("=========================================")
print(" EXAM GRADE REPORT SUMMARY ")
print("=========================================")
print(f"Number of Students : {len(scores)}")
print(f"Minimum Score : {np.min(scores)}")
print(f"Maximum Score : {np.max(scores)}")
print(f"Mean Score : {mean_val:.2f}")
print(f"Median Score : {median_val:.2f}")
print(f"Standard Deviation : {std_val:.2f}")
print("=========================================")

# Create the histogram plot
plt.figure(figsize=(10, 6))

# Customize the grid and style
plt.grid(axis='y', linestyle='--', alpha=0.7, zorder=0)

# Draw the histogram with bins of size 10 (0-10, 10-20, ..., 90-100)
bins = range(0, 111, 10)
plt.hist(scores, bins=bins, color='#4A90E2', edgecolor='black', rwidth=0.85, zorder=3)

# Add labels and title
plt.title('Distribution of Exam Scores', fontsize=16, fontweight='bold', pad=15)
plt.xlabel('Exam Scores', fontsize=12, labelpad=10)
plt.ylabel('Number of Students', fontsize=12, labelpad=10)

# Mark Mean and Median with vertical lines
plt.axvline(mean_val, color='#D0021B', linestyle='dashed', linewidth=2, zorder=4, label=f'Mean: {mean_val:.2f}')
plt.axvline(median_val, color='#F5A623', linestyle='dotted', linewidth=2, zorder=4, label=f'Median: {median_val:.2f}')

# Set x-ticks to align with bins
plt.xticks(range(0, 101, 10))

# Add a legend
plt.legend(fontsize=11, loc='upper left')

# Add details text box on the plot
textstr = '\n'.join((
    f'Total Students: {len(scores)}',
    f'Mean: {mean_val:.2f}',
    f'Median: {median_val:.2f}',
    f'Std Dev: {std_val:.2f}'
))
props = dict(boxstyle='round', facecolor='wheat', alpha=0.5)
plt.gca().text(0.05, 0.75, textstr, transform=plt.gca().transAxes, fontsize=10,
        verticalalignment='top', bbox=props)

# Adjust layout and save the figure
plt.tight_layout()
output_filename = 'grade_report.png'
plt.savefig(output_filename, dpi=300)
print(f"\nHistogram successfully saved to '{output_filename}'")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;if &lt;strong&gt;name&lt;/strong&gt; == ' &lt;strong&gt;main&lt;/strong&gt;':&lt;br&gt;
    generate_and_analyze_grades()&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
---

### 2. Output Statistics Summary

Upon running the script in the sandbox environment, it produced the following output:

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  text
&lt;/h1&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;     EXAM GRADE REPORT SUMMARY       
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;=========================================&lt;br&gt;
Number of Students : 100&lt;br&gt;
Minimum Score : 1&lt;br&gt;
Maximum Score : 100&lt;br&gt;
Mean Score : 51.31&lt;br&gt;
Median Score : 53.50&lt;/p&gt;
&lt;h1&gt;
  
  
  Standard Deviation : 29.70
&lt;/h1&gt;

&lt;p&gt;Histogram successfully saved to 'grade_report.png'&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
---

### 3. Generated Histogram Details (`grade_report.png`)

The script successfully outputted `grade_report.png` in high-resolution format (300 DPI) containing:
- **Clean Grid &amp;amp; Styling** : Standard light-gray horizontal grids to easily identify column heights.
- **Grade Bins** : Defined score ranges of size 10 (e.g., 0–10, 10–20, ..., 90–100) using custom spacing to give the columns a professional look.
- **Key Metrics Highlighted** : 
  - A red dashed line representing the **Mean** (`51.31`).
  - A yellow dotted line representing the **Median** (`53.50`).
- **An Info Legend and Box** : In the top-left area summarizing all descriptive statistics for easy offline reference.

### How to Run it Yourself
If you want to run this script in another environment, ensure you have the required packages installed:
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
bash&lt;br&gt;
pip install matplotlib numpy&lt;br&gt;
python generate_report.py&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
plaintext&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;📝 Note:&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;The agent’s response is a natural-language summary, not raw program output. It describes what it&lt;/em&gt; did &lt;em&gt;i.e. the code it wrote, the packages it installed, and the results. The actual Python script and chart file exist inside the remote sandbox.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;That’s it. &lt;strong&gt;3–4 lines of meaningful code that we can actually understand.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Behind the scenes, the agent:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Booted up an Ubuntu Linux sandbox&lt;/li&gt;
&lt;li&gt;Wrote a Python script that generates random data and computes statistics&lt;/li&gt;
&lt;li&gt;Auto-installed matplotlib (it wasn't asked to — it just knew it was needed)&lt;/li&gt;
&lt;li&gt;Executed the script, rendering a histogram to grade_report.png&lt;/li&gt;
&lt;li&gt;Returned a summary with the statistics and a confirmation that the chart was saved&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let’s try something more ambitious — a task that requires multiple tools:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from google import genai
client = genai.Client()

interaction = client.interactions.create(
    agent="antigravity-preview-05-2026",
    input="""
    Research the top 5 most popular Python web frameworks in 2026.
    For each framework:
    1. Find the latest version number and release date
    2. Count the GitHub stars
    3. Write a comparison table in Markdown
    """,
    environment="remote"
)

print(interaction.output_text)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
plaintext&lt;/p&gt;

&lt;p&gt;The agent will use &lt;strong&gt;web browsing&lt;/strong&gt; to search Google, &lt;strong&gt;code execution&lt;/strong&gt; to structure the data, and &lt;strong&gt;file management&lt;/strong&gt; to save the results , all autonomously, all within one API call.&lt;/p&gt;

&lt;p&gt;Here is the output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;The landscape of Python web development in **2026** is marked by a fascinating split [1, 2]. On one side, classic **backend-first** and **API-focused** frameworks (Django, FastAPI, Flask) remain the dominant standards for enterprise applications and microservices [3, 5]. On the other side, **pure-Python UI and full-stack** frameworks (Streamlit, Reflex) have seen explosive growth—driven by the need to build interactive web apps, data dashboards, and AI/ML interfaces without writing JavaScript or TypeScript [1, 2].

Below is an in-depth research report on the **top 5 most popular Python web frameworks in 2026** , ranked by GitHub stars and overall developer adoption.

---

### Detailed Breakdown of the Top 5 Python Web Frameworks

#### 1. FastAPI (99,034 GitHub Stars)
* **Latest Version:** `0.136.3` (Released: **May 23, 2026** )
* **Architecture Type:** ASGI (Asynchronous Server Gateway Interface)
* **Primary Focus:** High-Performance APIs and Microservices [4]
* **Core Philosophy:** FastAPI is designed to build APIs quickly with standard Python type hints. It leverages **Pydantic v2** for extremely fast data validation and serialization, and **Starlette** for high-concurrency async handling [3, 4]. It natively auto-generates interactive Swagger UI and ReDoc documentation.
* **Ideal Use Case:** AI/ML model deployment, backend APIs for single-page applications (React/Vue/Svelte), and low-latency microservices [5].

#### 2. Django (87,811 GitHub Stars)
* **Latest Version:** `6.0.6` (Released: **June 3, 2026** )
* **Architecture Type:** WSGI &amp;amp; ASGI (Fully async-supported)
* **Primary Focus:**"Batteries-Included" Monolithic Web Applications [4]
* **Core Philosophy:** As an 18-year industry standard, Django remains the premier full-featured web framework [2]. It handles everything—database routing (via its powerful ORM), administration panels, user authentication, form validation, and robust security defaults (SQLi, CSRF, XSS protection) [1]. In 2026, Django 6.x is highly optimized with full native asynchronous views and type hints [4].
* **Ideal Use Case:** Large-scale enterprise applications, content management systems, e-commerce platforms, and fast SaaS MVP development where you need a complete, secure architecture out of the box [2, 5].

#### 3. Flask (71,638 GitHub Stars)
* **Latest Version:** `3.1.3` (Released: **February 19, 2026** )
* **Architecture Type:** WSGI
* **Primary Focus:** Lightweight, Flexible Microframework [4]
* **Core Philosophy:** Flask provides a minimalist core, leaving the choice of database ORM, form handling, and security components completely up to the developer [1, 2]. Paired with modern 2026 extensions (SQLAlchemy 2.x, Pydantic), it represents a simple, un-opinionated foundation that never gets in the developer's way [3].
* **Ideal Use Case:** Small utility applications, lightweight APIs, microservices, and custom projects where developers want total control over their system design [1, 5].

#### 4. Streamlit (44,895 GitHub Stars)
* **Latest Version:** `1.58.0` (Released: **May 28, 2026** )
* **Architecture Type:** UI-First Scripting Paradigm
* **Primary Focus:** Rapid Data and Machine Learning Applications [1]
* **Core Philosophy:** Streamlit turns standard Python scripts into interactive, beautiful web apps in a matter of minutes. It handles the entire frontend and backend flow by re-running the script from top to bottom whenever a user interacts with a widget.
* **Ideal Use Case:** Quick data dashboards, machine learning model prototypes, and internal analytical tools for teams without frontend resources [1, 2].

#### 5. Reflex (28,467 GitHub Stars)
* **Latest Version:** `0.9.4` (Released: **June 4, 2026** )
* **Architecture Type:** Full-Stack Async React-Compiled
* **Primary Focus:** Interactive, Pure-Python Full-Stack Apps [2]
* **Core Philosophy:** Formerly known as Pynecone, Reflex compiles Python code into a high-performance **React/Next.js frontend** and a **FastAPI backend** , using real-time WebSockets to synchronize states between them [1, 2]. It bypasses JavaScript entirely, offering 60+ pre-built Radix UI components with native Tailwind integration [1, 2].
* **Ideal Use Case:** Complex, interactive web applications, real-time streaming dashboards (e.g., AI chat applications, financial trackers), and user-facing SaaS applications built entirely in Python [2].

---

### Other Honorable Mentions in 2026
While they didn't make the top 5 by GitHub stars, these frameworks are heavily utilized:
* **Tornado** (22,182 stars, v6.5.7, Released June 8, 2026): A mature, asynchronous networking framework ideal for long-lived WebSocket connections [4].
* **Sanic** (18,629 stars, v25.12.1, Released May 31, 2026): An ASGI web framework built for extreme speed and Flask-like simplicity, running on its own high-performance web server.
* **Litestar** (8,269 stars, v2.23.0, Released May 29, 2026): A highly structured, strict, and enterprise-grade ASGI alternative to FastAPI [3, 4].

---

### 2026 Python Web Frameworks Comparison Table

| Framework | GitHub Stars | Latest Version | Release Date | Architecture | Best For | Key Strength | Learning Curve |
| :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- |
| **FastAPI** | ~99,034 | `0.136.3` | May 23, 2026 | ASGI (Async) | High-performance API development &amp;amp; AI model deployments [4, 5] | Autogenerated Swagger docs, native Pydantic v2 validation [4] | **Easy / Moderate** |
| **Django** | ~87,811 | `6.0.6` | Jun 03, 2026 | WSGI / ASGI | Enterprise apps, content-heavy websites, secure SQL backends [1, 2] | "Batteries-included" (built-in admin, ORM, security, auth) [1, 2] | **Moderate / Hard** |
| **Flask** | ~71,638 | `3.1.3` | Feb 19, 2026 | WSGI (Sync-first) | Microservices, custom MVPs, lightweight apps [1, 5] | Unrivaled design flexibility, minimal core overhead [1] | **Very Easy** |
| **Streamlit** | ~44,895 | `1.58.0` | May 28, 2026 | Scripted Reactive | Data visualization dashboards &amp;amp; ML interactive tools [1] | Zero frontend experience needed; fast prototyping [1] | **Very Easy** |
| **Reflex** | ~28,467 | `0.9.4` | Jun 04, 2026 | Async React-compiled | Interactive, real-time SaaS &amp;amp; full-stack apps in pure Python [2] | True multi-page routing, state management without JavaScript [2] | **Moderate** |

---

### Guidance: Which Framework Should You Choose in 2026?

1. **Choose FastAPI** if you are building modern REST/GraphQL APIs, backend microservices, or deploying AI/ML models with high concurrency and automatic documentation [3, 5].
2. **Choose Django** if you are building database-driven business platforms or SaaS architectures where user authentication, administrative interfaces, and built-in security are paramount [1, 2].
3. **Choose Flask** if you need to build simple backend services or you want to hand-select every tool in your stack (e.g., combining custom database layers with external identity providers) [1].
4. **Choose Streamlit** if your core team consists of data scientists or business analysts who need to quickly present internal analytics, charts, and interactive widgets without building a complex web architecture [1, 2].
5. **Choose Reflex** if you want to build a fully interactive, production-ready full-stack application (with complex states, WebSocket interactions, and beautiful custom styles) but do not want to divide your team between Python and JavaScript [2].

---

### Sources &amp;amp; References
* [1] [Best Python Web Frameworks 2026 Compared - Reflex](https://reflex.dev/blog/top-python-web-frameworks/)
* [2] [Django vs Flask vs Reflex (April 2026) - Reflex](https://reflex.dev/blog/django-vs-flask-vs-reflex-comparison/)
* [3] [12 Modern Python Frameworks to Try in 2026 - Medium](https://medium.com/the-pythonworld/12-modern-python-frameworks-to-try-in-2026-e7089305bb19)
* [4] [5 top Python web frameworks of 2026 - Educative.io](https://www.educative.io/blog/top-python-web-frameworks)
* [5] [The Python Backend Framework Decision Guide for 2026 - Rollbar](https://rollbar.com/blog/python-backend-frameworks/)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
plaintext&lt;/p&gt;
&lt;h3&gt;
  
  
  Multi-Turn Conversations: Persistent Sandbox State
&lt;/h3&gt;

&lt;p&gt;What if you want the agent to build on its previous work? By default, each interactions.create() call spins up a &lt;strong&gt;brand-new, empty sandbox&lt;/strong&gt;. To continue in the same environment, you pass two IDs back:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from google import genai
client = genai.Client()

# Turn 1: Research and create a report
interaction_1 = client.interactions.create(
    agent="antigravity-preview-05-2026",
    input="Research the current state of carbon capture technology in 2026. "
          "Write a comprehensive 500-word report and save it as report.md",
    environment="remote"
)
print(f"Environment ID: {interaction_1.environment_id}")
print(f"Interaction ID: {interaction_1.id}")
print(interaction_1.output_text)

# Turn 2: Build on the previous work - same sandbox, same files
interaction_2 = client.interactions.create(
    agent="antigravity-preview-05-2026",
    environment=interaction_1.environment_id, # ← Re-attaches to same Ubuntu sandbox
    previous_interaction_id=interaction_1.id, # ← Preserves conversation memory
    input="Convert that report.md file into a clean index.html webpage "
          "with modern inline CSS styling and responsive design."
          " Please output the contents of the index.html file"
)
print(interaction_2.output_text)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
plaintext&lt;/p&gt;

&lt;p&gt;The first interaction produced the report.md file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Environment ID: 5eb9b4b8-c02f-4a8f-b7a0-c90a796c01a6
Interaction ID: v1_ChdidXNuYXJLQkF1eWlqdU1QODRmUjJRZxIXYnVzbmFyS0JBdXlpanVNUDg0ZlIyUWc
I have researched the state of carbon capture, utilization, and storage (CCUS)
technology in 2026 and compiled a comprehensive 494-word report. 
The report has been successfully saved to your environment as **`report.md`**.

Below is the full text of the report, 
highlighting how the CCUS sector has transitioned from pilot-stage 
demonstrations to industrial infrastructure in 2026.

***

# The State of Carbon Capture Technology in 2026: From Pilot to Infrastructure

## Executive Summary
....

## Point-Source Capture: The Current Backbone
...

## Scaling Direct Air Capture (DAC)
... 

## Infrastructure, Transport, and Policy
...

## Key Challenges
...

***

### Sources Cited

* **[1] S&amp;amp;P Global:** [2026 CCUS: Navigating the tides of the great realignment](https://www.spglobal.com/energy/en/news-research/blog/energy-transition/041426-2026-ccus-navigating-the-tides-of-the-great-realignment) (April 2026)
* **[2] Carbon Herald:** [What's Next For Carbon Capture, Utilization &amp;amp; Storage (CCUS) In 2026](https://carbonherald.com/whats-next-for-carbon-capture-utilization-storage-ccus-in-2026/) (January 2026)
* **[3] Nature Tech Memos:** [Top 10 Carbon Capture Startups for Corporate Partnerships in 2026](https://www.naturetechmemos.com/p/top-10-carbon-capture-startups-for-corporate-partnerships-in-2026) (April 2026)
.....

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
plaintext&lt;/p&gt;

&lt;p&gt;The second interaction continued with the previous environment and interaction, and asked it to produce an HTML version of it i.e. index.html. The instruction specifically asked for the HTML contents to be produced.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;I have successfully converted your `report.md` file into a clean, modern, and highly responsive **`index.html`** webpage! 

### What was done:
1. **Designed a cohesive palette:** Implemented a modern climate-tech inspired aesthetic using Slate (`#1e293b`) and a range of deep and light teals (`#0f766e`, `#14b8a6`, `#115e59`).
2. **Added an Interactive Stat Dashboard:** Created a high-level statistical summary card grid displaying key 2026 data at a glance (e.g., global Mtpa capacity, Stratos targets, US Section 45Q tax credits).
3. **Structured visual highlights:** Embedded two distinct grid comparison cards for the **Climeworks Mammoth** and **1PointFive Stratos** facilities, as well as a custom callout block highlighting the trans-European **Northern Lights** shipping route.
4. **Professionalized the typography &amp;amp; chemistry:** Used system-ui fonts for excellent loading speeds and correctly formatted all chemical formulas to standard subscripts (e.g., **CO&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt;** ).
5. **Citations &amp;amp; Interactivity:** Mapped the original references into clickable, superscript citation numbers (e.g., `[1]`) that link smoothly down to a beautifully bulleted "Sources Cited" section with custom index bullet styling.

The full HTML contents of the newly created `index.html` are shown below:

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
html&lt;br&gt;
&amp;lt;!DOCTYPE html&amp;gt;&lt;br&gt;
&lt;br&gt;
&lt;br&gt;
    &lt;br&gt;
    &lt;br&gt;
    &lt;/p&gt;
The State of Carbon Capture Technology in 2026
&lt;br&gt;
    &amp;lt;br&amp;gt;
        :root {&amp;lt;br&amp;gt;
            --primary: #0f766e;&amp;lt;br&amp;gt;
            --primary-light: #14b8a6;&amp;lt;br&amp;gt;
            --primary-dark: #115e59;&amp;lt;br&amp;gt;
            --bg: #f8fafc;&amp;lt;br&amp;gt;
            --card-bg: #ffffff;&amp;lt;br&amp;gt;
            --text-main: #1e293b;&amp;lt;br&amp;gt;
            --text-muted: #475569;&amp;lt;br&amp;gt;
            --accent: #0284c7;&amp;lt;br&amp;gt;
            --border: #e2e8f0;&amp;lt;br&amp;gt;
            --shadow: 0 4px 6px -1px rgba(15, 118, 110, 0.05), 0 2px 4px -2px rgba(15, 118, 110, 0.05);&amp;lt;br&amp;gt;
            --shadow-md: 0 10px 15px -3px rgba(15, 118, 110, 0.1), 0 4px 6px -4px rgba(15, 118, 110, 0.1);&amp;lt;br&amp;gt;
        }&amp;lt;br&amp;gt;
        * {&amp;lt;br&amp;gt;
            box-sizing: border-box;&amp;lt;br&amp;gt;
        }&amp;lt;br&amp;gt;
        body {&amp;lt;br&amp;gt;
            font-family: -apple-system, BlinkMacSystemFont, &amp;amp;quot;Segoe UI&amp;amp;quot;, Roboto, Helvetica, Arial, sans-serif;&amp;lt;br&amp;gt;
            background-color: var(--bg);&amp;lt;br&amp;gt;
            color: var(--text-main);&amp;lt;br&amp;gt;
            line-height: 1.8;&amp;lt;br&amp;gt;
            margin: 0;&amp;lt;br&amp;gt;
            padding: 0;&amp;lt;br&amp;gt;
            -webkit-font-smoothing: antialiased;&amp;lt;br&amp;gt;
        }&amp;lt;br&amp;gt;
        header {&amp;lt;br&amp;gt;
            background: linear-gradient(135deg, #0d5c56 0%, #0f766e 50%, #115e59 100%);&amp;lt;br&amp;gt;
            color: white;&amp;lt;br&amp;gt;
            padding: 5rem 2rem;&amp;lt;br&amp;gt;
            text-align: center;&amp;lt;br&amp;gt;
            position: relative;&amp;lt;br&amp;gt;
        }&amp;lt;br&amp;gt;
        header::after {&amp;lt;br&amp;gt;
            content: &amp;amp;#39;&amp;amp;#39;;&amp;lt;br&amp;gt;
            position: absolute;&amp;lt;br&amp;gt;
            bottom: 0;&amp;lt;br&amp;gt;
            left: 0;&amp;lt;br&amp;gt;
            right: 0;&amp;lt;br&amp;gt;
            height: 6px;&amp;lt;br&amp;gt;
            background: linear-gradient(90deg, var(--primary-light), var(--accent));&amp;lt;br&amp;gt;
        }&amp;lt;br&amp;gt;
        .header-content {&amp;lt;br&amp;gt;
            max-width: 800px;&amp;lt;br&amp;gt;
            margin: 0 auto;&amp;lt;br&amp;gt;
        }&amp;lt;br&amp;gt;
        header h1 {&amp;lt;br&amp;gt;
            font-size: 2.75rem;&amp;lt;br&amp;gt;
            font-weight: 800;&amp;lt;br&amp;gt;
            margin: 0 0 1rem 0;&amp;lt;br&amp;gt;
            letter-spacing: -0.025em;&amp;lt;br&amp;gt;
            line-height: 1.2;&amp;lt;br&amp;gt;
        }&amp;lt;br&amp;gt;
        header p {&amp;lt;br&amp;gt;
            font-size: 1.25rem;&amp;lt;br&amp;gt;
            color: #ccfbf1;&amp;lt;br&amp;gt;
            margin: 0 0 1.5rem 0;&amp;lt;br&amp;gt;
            font-weight: 300;&amp;lt;br&amp;gt;
        }&amp;lt;br&amp;gt;
        .meta {&amp;lt;br&amp;gt;
            font-size: 0.875rem;&amp;lt;br&amp;gt;
            color: #99f6e4;&amp;lt;br&amp;gt;
            text-transform: uppercase;&amp;lt;br&amp;gt;
            letter-spacing: 0.125em;&amp;lt;br&amp;gt;
            font-weight: 600;&amp;lt;br&amp;gt;
        }&amp;lt;br&amp;gt;
        main {&amp;lt;br&amp;gt;
            max-width: 900px;&amp;lt;br&amp;gt;
            margin: -3rem auto 4rem auto;&amp;lt;br&amp;gt;
            padding: 0 1.5rem;&amp;lt;br&amp;gt;
            position: relative;&amp;lt;br&amp;gt;
            z-index: 10;&amp;lt;br&amp;gt;
        }&amp;lt;br&amp;gt;
        .stats-grid {&amp;lt;br&amp;gt;
            display: grid;&amp;lt;br&amp;gt;
            grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));&amp;lt;br&amp;gt;
            gap: 1.5rem;&amp;lt;br&amp;gt;
            margin-bottom: 3rem;&amp;lt;br&amp;gt;
        }&amp;lt;br&amp;gt;
        .stat-card {&amp;lt;br&amp;gt;
            background: var(--card-bg);&amp;lt;br&amp;gt;
            padding: 1.75rem 1.5rem;&amp;lt;br&amp;gt;
            border-radius: 14px;&amp;lt;br&amp;gt;
            box-shadow: var(--shadow);&amp;lt;br&amp;gt;
            border: 1px solid var(--border);&amp;lt;br&amp;gt;
            text-align: center;&amp;lt;br&amp;gt;
            transition: transform 0.25s ease, box-shadow 0.25s ease;&amp;lt;br&amp;gt;
        }&amp;lt;br&amp;gt;
        .stat-card:hover {&amp;lt;br&amp;gt;
            transform: translateY(-5px);&amp;lt;br&amp;gt;
            box-shadow: var(--shadow-md);&amp;lt;br&amp;gt;
        }&amp;lt;br&amp;gt;
        .stat-num {&amp;lt;br&amp;gt;
            font-size: 2.25rem;&amp;lt;br&amp;gt;
            font-weight: 800;&amp;lt;br&amp;gt;
            color: var(--primary);&amp;lt;br&amp;gt;
            margin-bottom: 0.5rem;&amp;lt;br&amp;gt;
            line-height: 1;&amp;lt;br&amp;gt;
        }&amp;lt;br&amp;gt;
        .stat-label {&amp;lt;br&amp;gt;
            font-size: 0.875rem;&amp;lt;br&amp;gt;
            color: var(--text-muted);&amp;lt;br&amp;gt;
            font-weight: 600;&amp;lt;br&amp;gt;
            text-transform: uppercase;&amp;lt;br&amp;gt;
            letter-spacing: 0.05em;&amp;lt;br&amp;gt;
        }&amp;lt;br&amp;gt;
        .content-wrapper {&amp;lt;br&amp;gt;
            background: var(--card-bg);&amp;lt;br&amp;gt;
            padding: 4rem 3.5rem;&amp;lt;br&amp;gt;
            border-radius: 20px;&amp;lt;br&amp;gt;
            box-shadow: var(--shadow-md);&amp;lt;br&amp;gt;
            border: 1px solid var(--border);&amp;lt;br&amp;gt;
        }&amp;lt;br&amp;gt;
        section {&amp;lt;br&amp;gt;
            margin-bottom: 3.5rem;&amp;lt;br&amp;gt;
        }&amp;lt;br&amp;gt;
        section:last-of-type {&amp;lt;br&amp;gt;
            margin-bottom: 0;&amp;lt;br&amp;gt;
        }&amp;lt;br&amp;gt;
        h2 {&amp;lt;br&amp;gt;
            color: var(--primary-dark);&amp;lt;br&amp;gt;
            font-size: 1.85rem;&amp;lt;br&amp;gt;
            font-weight: 700;&amp;lt;br&amp;gt;
            margin-top: 0;&amp;lt;br&amp;gt;
            margin-bottom: 1.5rem;&amp;lt;br&amp;gt;
            border-bottom: 2px solid #f1f5f9;&amp;lt;br&amp;gt;
            padding-bottom: 0.75rem;&amp;lt;br&amp;gt;
        }&amp;lt;br&amp;gt;
        p {&amp;lt;br&amp;gt;
            margin-top: 0;&amp;lt;br&amp;gt;
            margin-bottom: 1.5rem;&amp;lt;br&amp;gt;
            font-size: 1.1rem;&amp;lt;br&amp;gt;
            color: #334155;&amp;lt;br&amp;gt;
            text-align: justify;&amp;lt;br&amp;gt;
        }&amp;lt;br&amp;gt;
        .highlight-grid {&amp;lt;br&amp;gt;
            display: grid;&amp;lt;br&amp;gt;
            grid-template-columns: 1fr 1fr;&amp;lt;br&amp;gt;
            gap: 1.5rem;&amp;lt;br&amp;gt;
            margin: 2rem 0;&amp;lt;br&amp;gt;
        }&amp;lt;br&amp;gt;
        @media (max-width: 768px) {&amp;lt;br&amp;gt;
            header h1 {&amp;lt;br&amp;gt;
                font-size: 2.25rem;&amp;lt;br&amp;gt;
            }&amp;lt;br&amp;gt;
            .content-wrapper {&amp;lt;br&amp;gt;
                padding: 2.5rem 1.5rem;&amp;lt;br&amp;gt;
            }&amp;lt;br&amp;gt;
            .highlight-grid {&amp;lt;br&amp;gt;
                grid-template-columns: 1fr;&amp;lt;br&amp;gt;
            }&amp;lt;br&amp;gt;
        }&amp;lt;br&amp;gt;
        .highlight-box {&amp;lt;br&amp;gt;
            background: #f0fdfa;&amp;lt;br&amp;gt;
            border: 1px solid #ccfbf1;&amp;lt;br&amp;gt;
            padding: 1.5rem;&amp;lt;br&amp;gt;
            border-radius: 12px;&amp;lt;br&amp;gt;
            border-left: 5px solid var(--primary);&amp;lt;br&amp;gt;
        }&amp;lt;br&amp;gt;
        .highlight-box h4 {&amp;lt;br&amp;gt;
            margin: 0 0 0.75rem 0;&amp;lt;br&amp;gt;
            color: var(--primary-dark);&amp;lt;br&amp;gt;
            font-size: 1.15rem;&amp;lt;br&amp;gt;
            font-weight: 700;&amp;lt;br&amp;gt;
        }&amp;lt;br&amp;gt;
        .highlight-box p {&amp;lt;br&amp;gt;
            margin: 0;&amp;lt;br&amp;gt;
            font-size: 0.95rem;&amp;lt;br&amp;gt;
            color: #0f766e;&amp;lt;br&amp;gt;
            text-align: left;&amp;lt;br&amp;gt;
            line-height: 1.6;&amp;lt;br&amp;gt;
        }&amp;lt;br&amp;gt;
        .callout {&amp;lt;br&amp;gt;
            background: #f8fafc;&amp;lt;br&amp;gt;
            border: 1px solid var(--border);&amp;lt;br&amp;gt;
            border-left: 5px solid var(--accent);&amp;lt;br&amp;gt;
            padding: 1.5rem;&amp;lt;br&amp;gt;
            border-radius: 4px 12px 12px 4px;&amp;lt;br&amp;gt;
            margin: 2rem 0;&amp;lt;br&amp;gt;
        }&amp;lt;br&amp;gt;
        .callout-title {&amp;lt;br&amp;gt;
            font-weight: 700;&amp;lt;br&amp;gt;
            color: #0369a1;&amp;lt;br&amp;gt;
            margin-bottom: 0.5rem;&amp;lt;br&amp;gt;
            font-size: 1.1rem;&amp;lt;br&amp;gt;
        }&amp;lt;br&amp;gt;
        .callout p {&amp;lt;br&amp;gt;
            margin: 0;&amp;lt;br&amp;gt;
            font-size: 1rem;&amp;lt;br&amp;gt;
            color: #475569;&amp;lt;br&amp;gt;
            text-align: left;&amp;lt;br&amp;gt;
        }&amp;lt;br&amp;gt;
        .citation-link {&amp;lt;br&amp;gt;
            color: var(--primary);&amp;lt;br&amp;gt;
            text-decoration: none;&amp;lt;br&amp;gt;
            font-weight: 700;&amp;lt;br&amp;gt;
            font-size: 0.85rem;&amp;lt;br&amp;gt;
            padding: 0 2px;&amp;lt;br&amp;gt;
            vertical-align: super;&amp;lt;br&amp;gt;
        }&amp;lt;br&amp;gt;
        .citation-link:hover {&amp;lt;br&amp;gt;
            color: var(--accent);&amp;lt;br&amp;gt;
            text-decoration: underline;&amp;lt;br&amp;gt;
        }&amp;lt;br&amp;gt;
        .sources-section {&amp;lt;br&amp;gt;
            background: #f8fafc;&amp;lt;br&amp;gt;
            border: 1px solid var(--border);&amp;lt;br&amp;gt;
            margin-top: 4rem;&amp;lt;br&amp;gt;
            padding: 2.5rem;&amp;lt;br&amp;gt;
            border-radius: 14px;&amp;lt;br&amp;gt;
        }&amp;lt;br&amp;gt;
        .sources-section h3 {&amp;lt;br&amp;gt;
            margin-top: 0;&amp;lt;br&amp;gt;
            color: var(--primary-dark);&amp;lt;br&amp;gt;
            font-size: 1.35rem;&amp;lt;br&amp;gt;
            margin-bottom: 1.5rem;&amp;lt;br&amp;gt;
            font-weight: 700;&amp;lt;br&amp;gt;
        }&amp;lt;br&amp;gt;
        .sources-list {&amp;lt;br&amp;gt;
            list-style-type: none;&amp;lt;br&amp;gt;
            padding: 0;&amp;lt;br&amp;gt;
            margin: 0;&amp;lt;br&amp;gt;
        }&amp;lt;br&amp;gt;
        .sources-list li {&amp;lt;br&amp;gt;
            margin-bottom: 1rem;&amp;lt;br&amp;gt;
            font-size: 0.95rem;&amp;lt;br&amp;gt;
            padding-left: 2rem;&amp;lt;br&amp;gt;
            position: relative;&amp;lt;br&amp;gt;
            line-height: 1.6;&amp;lt;br&amp;gt;
            color: #475569;&amp;lt;br&amp;gt;
        }&amp;lt;br&amp;gt;
        .sources-list li::before {&amp;lt;br&amp;gt;
            content: attr(data-index);&amp;lt;br&amp;gt;
            color: var(--primary);&amp;lt;br&amp;gt;
            position: absolute;&amp;lt;br&amp;gt;
            left: 0;&amp;lt;br&amp;gt;
            font-weight: 700;&amp;lt;br&amp;gt;
            background: #ccfbf1;&amp;lt;br&amp;gt;
            width: 24px;&amp;lt;br&amp;gt;
            height: 24px;&amp;lt;br&amp;gt;
            border-radius: 50%;&amp;lt;br&amp;gt;
            display: flex;&amp;lt;br&amp;gt;
            align-items: center;&amp;lt;br&amp;gt;
            justify-content: center;&amp;lt;br&amp;gt;
            font-size: 0.75rem;&amp;lt;br&amp;gt;
            top: 2px;&amp;lt;br&amp;gt;
        }&amp;lt;br&amp;gt;
        .sources-list a {&amp;lt;br&amp;gt;
            color: var(--primary-dark);&amp;lt;br&amp;gt;
            text-decoration: none;&amp;lt;br&amp;gt;
            font-weight: 600;&amp;lt;br&amp;gt;
            transition: color 0.2s ease;&amp;lt;br&amp;gt;
        }&amp;lt;br&amp;gt;
        .sources-list a:hover {&amp;lt;br&amp;gt;
            color: var(--accent);&amp;lt;br&amp;gt;
            text-decoration: underline;&amp;lt;br&amp;gt;
        }&amp;lt;br&amp;gt;
        footer {&amp;lt;br&amp;gt;
            text-align: center;&amp;lt;br&amp;gt;
            color: var(--text-muted);&amp;lt;br&amp;gt;
            font-size: 0.875rem;&amp;lt;br&amp;gt;
            margin-top: 4rem;&amp;lt;br&amp;gt;
            padding-top: 2rem;&amp;lt;br&amp;gt;
            border-top: 1px solid var(--border);&amp;lt;br&amp;gt;
        }&amp;lt;br&amp;gt;
    &lt;br&gt;
&lt;br&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;header&amp;gt;
    &amp;lt;div class="header-content"&amp;gt;
        &amp;lt;span class="meta"&amp;gt;Special Intelligence Report&amp;lt;/span&amp;gt;
        &amp;lt;h1&amp;gt;The State of Carbon Capture Technology in 2026&amp;lt;/h1&amp;gt;
        &amp;lt;p&amp;gt;From Pilot to Infrastructure&amp;lt;/p&amp;gt;
    &amp;lt;/div&amp;gt;
&amp;lt;/header&amp;gt;

&amp;lt;main&amp;gt;
    &amp;lt;!-- Key Metrics Dashboard --&amp;gt;
    &amp;lt;div class="stats-grid"&amp;gt;
        &amp;lt;div class="stat-card"&amp;gt;
            &amp;lt;div class="stat-num"&amp;gt;~73 Mtpa&amp;lt;/div&amp;gt;
            &amp;lt;div class="stat-label"&amp;gt;Global Operational Capacity&amp;lt;/div&amp;gt;
        &amp;lt;/div&amp;gt;
        &amp;lt;div class="stat-card"&amp;gt;
            &amp;lt;div class="stat-num"&amp;gt;500k Tons&amp;lt;/div&amp;gt;
            &amp;lt;div class="stat-label"&amp;gt;Stratos DAC Annual Target&amp;lt;/div&amp;gt;
        &amp;lt;/div&amp;gt;
        &amp;lt;div class="stat-card"&amp;gt;
            &amp;lt;div class="stat-num"&amp;gt;Up to $180&amp;lt;/div&amp;gt;
            &amp;lt;div class="stat-label"&amp;gt;US 45Q Subsidy per Ton&amp;lt;/div&amp;gt;
        &amp;lt;/div&amp;gt;
        &amp;lt;div class="stat-card"&amp;gt;
            &amp;lt;div class="stat-num"&amp;gt;36,000 T&amp;lt;/div&amp;gt;
            &amp;lt;div class="stat-label"&amp;gt;Mammoth Iceland Capacity&amp;lt;/div&amp;gt;
        &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;

    &amp;lt;div class="content-wrapper"&amp;gt;
        &amp;lt;!-- Executive Summary --&amp;gt;
        &amp;lt;section id="executive-summary"&amp;gt;
            &amp;lt;h2&amp;gt;Executive Summary&amp;lt;/h2&amp;gt;
            &amp;lt;p&amp;gt;
                In 2026, the Carbon Capture, Utilization, and Storage (CCUS) industry is undergoing an "industrial hardening" phase, transitioning decisively from demonstration-stage pilots to commercial-scale infrastructure&amp;lt;sup&amp;gt;&amp;lt;a href="#ref-1" class="citation-link"&amp;gt;[1]&amp;lt;/a&amp;gt;&amp;lt;/sup&amp;gt;. Global operational capture capacity has reached approximately 73 million metric tons per annum (Mtpa) as of mid-2026, up from 50 Mtpa in early 2025&amp;lt;sup&amp;gt;&amp;lt;a href="#ref-1" class="citation-link"&amp;gt;[1]&amp;lt;/a&amp;gt;&amp;lt;/sup&amp;gt;&amp;lt;sup&amp;gt;&amp;lt;a href="#ref-2" class="citation-link"&amp;gt;[2]&amp;lt;/a&amp;gt;&amp;lt;/sup&amp;gt;. This momentum is propelled by robust climate policies, corporate carbon-removal commitments, and the commissioning of megaton-scale facilities.
            &amp;lt;/p&amp;gt;
        &amp;lt;/section&amp;gt;

        &amp;lt;!-- Point-Source Capture --&amp;gt;
        &amp;lt;section id="point-source"&amp;gt;
            &amp;lt;h2&amp;gt;Point-Source Capture: The Current Backbone&amp;lt;/h2&amp;gt;
            &amp;lt;p&amp;gt;
                Point-source carbon capture remains the commercial backbone of CCUS&amp;lt;sup&amp;gt;&amp;lt;a href="#ref-2" class="citation-link"&amp;gt;[2]&amp;lt;/a&amp;gt;&amp;lt;/sup&amp;gt;. Technologies deployed at industrial and energy facilities—such as cement, steel, chemicals, and refining—now represent the vast majority of active capture capacity. Post-combustion chemical absorption using amine-based solvents is the most widely deployed technology&amp;lt;sup&amp;gt;&amp;lt;a href="#ref-2" class="citation-link"&amp;gt;[2]&amp;lt;/a&amp;gt;&amp;lt;/sup&amp;gt;. Companies like Carbon Upcycling Technologies are successfully integrating capture systems with utilization, converting captured carbon dioxide (CO&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt;) into high-quality construction materials, turning emissions from cement manufacturers into a low-carbon concrete feedstock&amp;lt;sup&amp;gt;&amp;lt;a href="#ref-3" class="citation-link"&amp;gt;[3]&amp;lt;/a&amp;gt;&amp;lt;/sup&amp;gt;.
            &amp;lt;/p&amp;gt;
        &amp;lt;/section&amp;gt;

        &amp;lt;!-- Scaling Direct Air Capture --&amp;gt;
        &amp;lt;section id="dac"&amp;gt;
            &amp;lt;h2&amp;gt;Scaling Direct Air Capture (DAC)&amp;lt;/h2&amp;gt;
            &amp;lt;p&amp;gt;
                Direct Air Capture is experiencing a dramatic scale-up&amp;lt;sup&amp;gt;&amp;lt;a href="#ref-4" class="citation-link"&amp;gt;[4]&amp;lt;/a&amp;gt;&amp;lt;/sup&amp;gt;. Climeworks' "Mammoth" facility in Iceland, operational since May 2024, captures up to 36,000 tons of CO&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt; annually, storing it permanently underground via Carbfix mineralization&amp;lt;sup&amp;gt;&amp;lt;a href="#ref-4" class="citation-link"&amp;gt;[4]&amp;lt;/a&amp;gt;&amp;lt;/sup&amp;gt;&amp;lt;sup&amp;gt;&amp;lt;a href="#ref-5" class="citation-link"&amp;gt;[5]&amp;lt;/a&amp;gt;&amp;lt;/sup&amp;gt;. Meanwhile, 1PointFive's (a subsidiary of Occidental Petroleum) "Stratos" facility in Ector County, Texas, is entering active operation in 2026&amp;lt;sup&amp;gt;&amp;lt;a href="#ref-4" class="citation-link"&amp;gt;[4]&amp;lt;/a&amp;gt;&amp;lt;/sup&amp;gt;. Designed to capture up to 500,000 tons of atmospheric CO&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt; annually using liquid solvent technology licensed from Carbon Engineering, Stratos is currently the world’s largest DAC plant&amp;lt;sup&amp;gt;&amp;lt;a href="#ref-4" class="citation-link"&amp;gt;[4]&amp;lt;/a&amp;gt;&amp;lt;/sup&amp;gt;&amp;lt;sup&amp;gt;&amp;lt;a href="#ref-6" class="citation-link"&amp;gt;[6]&amp;lt;/a&amp;gt;&amp;lt;/sup&amp;gt;. 
            &amp;lt;/p&amp;gt;

            &amp;lt;div class="highlight-grid"&amp;gt;
                &amp;lt;div class="highlight-box"&amp;gt;
                    &amp;lt;h4&amp;gt;Climeworks: Mammoth (Iceland)&amp;lt;/h4&amp;gt;
                    &amp;lt;p&amp;gt;Nameplate capacity of 36,000 tons/year. Relies on solid-sorbent collectors powered by clean geothermal energy with deep Carbfix basaltic storage.&amp;lt;/p&amp;gt;
                &amp;lt;/div&amp;gt;
                &amp;lt;div class="highlight-box"&amp;gt;
                    &amp;lt;h4&amp;gt;1PointFive: Stratos (Texas)&amp;lt;/h4&amp;gt;
                    &amp;lt;p&amp;gt;World's largest facility with 500,000 tons/year target. Employs liquid-solvent infrastructure designed for rapid regional scalability.&amp;lt;/p&amp;gt;
                &amp;lt;/div&amp;gt;
            &amp;lt;/div&amp;gt;

            &amp;lt;p&amp;gt;
                Major technology firms (including Microsoft, Google, Meta, and Amazon) have signed multi-year offtake agreements for high-quality, durable carbon credits, paying between $200 and $300 per ton, though current baseline DAC capture costs remain high, between $400 and $1,000 per ton&amp;lt;sup&amp;gt;&amp;lt;a href="#ref-3" class="citation-link"&amp;gt;[3]&amp;lt;/a&amp;gt;&amp;lt;/sup&amp;gt;&amp;lt;sup&amp;gt;&amp;lt;a href="#ref-7" class="citation-link"&amp;gt;[7]&amp;lt;/a&amp;gt;&amp;lt;/sup&amp;gt;.
            &amp;lt;/p&amp;gt;
        &amp;lt;/section&amp;gt;

        &amp;lt;!-- Infrastructure, Transport, and Policy --&amp;gt;
        &amp;lt;section id="infrastructure"&amp;gt;
            &amp;lt;h2&amp;gt;Infrastructure, Transport, and Policy&amp;lt;/h2&amp;gt;
            &amp;lt;p&amp;gt;
                The commercial viability of carbon capture relies heavily on dedicated transportation and storage networks&amp;lt;sup&amp;gt;&amp;lt;a href="#ref-2" class="citation-link"&amp;gt;[2]&amp;lt;/a&amp;gt;&amp;lt;/sup&amp;gt;. In Europe, 2026 marks the active operation of Norway’s "Northern Lights" project, the world's first open-source CO&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt; transport and storage network&amp;lt;sup&amp;gt;&amp;lt;a href="#ref-8" class="citation-link"&amp;gt;[8]&amp;lt;/a&amp;gt;&amp;lt;/sup&amp;gt;. For example, Yara's flagship Sluiskil ammonia plant in the Netherlands is liquefying up to 800,000 tons of CO&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt; annually to be shipped by Northern Lights for permanent undersea storage&amp;lt;sup&amp;gt;&amp;lt;a href="#ref-8" class="citation-link"&amp;gt;[8]&amp;lt;/a&amp;gt;&amp;lt;/sup&amp;gt;. Concurrently, Denmark’s "Greensand" offshore storage initiative is beginning operations&amp;lt;sup&amp;gt;&amp;lt;a href="#ref-2" class="citation-link"&amp;gt;[2]&amp;lt;/a&amp;gt;&amp;lt;/sup&amp;gt;. 
            &amp;lt;/p&amp;gt;

            &amp;lt;div class="callout"&amp;gt;
                &amp;lt;div class="callout-title"&amp;gt;The Trans-European Shipping Pathway&amp;lt;/div&amp;gt;
                &amp;lt;p&amp;gt;Northern Lights bridges emission-heavy inland industrial sites like Yara Sluiskil in the Netherlands directly with permanent injection storage wells beneath the North Sea seabed.&amp;lt;/p&amp;gt;
            &amp;lt;/div&amp;gt;

            &amp;lt;p&amp;gt;
                On the policy front, the sector is heavily anchored by government subsidies. In the United States, the Inflation Reduction Act’s (IRA) modified Section 45Q tax credit provides up to $180 per metric ton for DAC and $85 per metric ton for point-source capture&amp;lt;sup&amp;gt;&amp;lt;a href="#ref-9" class="citation-link"&amp;gt;[9]&amp;lt;/a&amp;gt;&amp;lt;/sup&amp;gt;. In the European Union, the Net Zero Industry Act has accelerated cross-border transport approvals, providing regulatory certainty.
            &amp;lt;/p&amp;gt;
        &amp;lt;/section&amp;gt;

        &amp;lt;!-- Key Challenges --&amp;gt;
        &amp;lt;section id="challenges"&amp;gt;
            &amp;lt;h2&amp;gt;Key Challenges&amp;lt;/h2&amp;gt;
            &amp;lt;p&amp;gt;
                Despite rapid progress, critical bottlenecks persist. Chief among these is the high energy intensity of DAC, which requires 1.5 to 2.5 megawatt-hours (MWh) of zero-carbon energy per ton of captured CO&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt;&amp;lt;sup&amp;gt;&amp;lt;a href="#ref-7" class="citation-link"&amp;gt;[7]&amp;lt;/a&amp;gt;&amp;lt;/sup&amp;gt;. Permitting delays for geologic injection wells—specifically the EPA’s rigorous Class VI permits in the United States—also restrict how fast captured carbon can be sequestered&amp;lt;sup&amp;gt;&amp;lt;a href="#ref-4" class="citation-link"&amp;gt;[4]&amp;lt;/a&amp;gt;&amp;lt;/sup&amp;gt;. Overcoming these economic and infrastructure hurdles remains essential to achieving megaton targets by 2030.
            &amp;lt;/p&amp;gt;
        &amp;lt;/section&amp;gt;

        &amp;lt;!-- Sources Cited --&amp;gt;
        &amp;lt;div class="sources-section"&amp;gt;
            &amp;lt;h3&amp;gt;Sources Cited&amp;lt;/h3&amp;gt;
            &amp;lt;ul class="sources-list"&amp;gt;
                &amp;lt;li id="ref-1" data-index="1"&amp;gt;&amp;lt;strong&amp;gt;S&amp;amp;P Global:&amp;lt;/strong&amp;gt; &amp;lt;a href="https://www.spglobal.com/energy/en/news-research/blog/energy-transition/041426-2026-ccus-navigating-the-tides-of-the-great-realignment" target="_blank"&amp;gt;2026 CCUS: Navigating the tides of the great realignment&amp;lt;/a&amp;gt; (April 2026)&amp;lt;/li&amp;gt;
                &amp;lt;li id="ref-2" data-index="2"&amp;gt;&amp;lt;strong&amp;gt;Carbon Herald:&amp;lt;/strong&amp;gt; &amp;lt;a href="https://carbonherald.com/whats-next-for-carbon-capture-utilization-storage-ccus-in-2026/" target="_blank"&amp;gt;What's Next For Carbon Capture, Utilization &amp;amp; Storage (CCUS) In 2026&amp;lt;/a&amp;gt; (January 2026)&amp;lt;/li&amp;gt;
                &amp;lt;li id="ref-3" data-index="3"&amp;gt;&amp;lt;strong&amp;gt;Nature Tech Memos:&amp;lt;/strong&amp;gt; &amp;lt;a href="https://www.naturetechmemos.com/p/top-10-carbon-capture-startups-for-corporate-partnerships-in-2026" target="_blank"&amp;gt;Top 10 Carbon Capture Startups for Corporate Partnerships in 2026&amp;lt;/a&amp;gt; (April 2026)&amp;lt;/li&amp;gt;
                &amp;lt;li id="ref-4" data-index="4"&amp;gt;&amp;lt;strong&amp;gt;Senken:&amp;lt;/strong&amp;gt; &amp;lt;a href="https://www.senken.io/blog/top-direct-air-capture-carbon-removal-projects-buyers-guide" target="_blank"&amp;gt;The Top 3 Direct Air Capture Carbon Removal Projects&amp;lt;/a&amp;gt; (February 2026)&amp;lt;/li&amp;gt;
                &amp;lt;li id="ref-5" data-index="5"&amp;gt;&amp;lt;strong&amp;gt;Climeworks:&amp;lt;/strong&amp;gt; &amp;lt;a href="https://climeworks.com/plant-mammoth" target="_blank"&amp;gt;Mammoth: our newest direct air capture and storage facility&amp;lt;/a&amp;gt; (May 2024)&amp;lt;/li&amp;gt;
                &amp;lt;li id="ref-6" data-index="6"&amp;gt;&amp;lt;strong&amp;gt;Carbon Credits:&amp;lt;/strong&amp;gt; &amp;lt;a href="https://carboncredits.com/top-3-carbon-capture-leaders-to-drive-the-net-zero-race-in-2026/" target="_blank"&amp;gt;Top 3 Carbon Capture Leaders to Drive the Net-Zero Race in 2026&amp;lt;/a&amp;gt; (January 2026)&amp;lt;/li&amp;gt;
                &amp;lt;li id="ref-7" data-index="7"&amp;gt;&amp;lt;strong&amp;gt;Energy Solutions Intelligence:&amp;lt;/strong&amp;gt; &amp;lt;a href="https://energy-solutions.co/articles/sub/carbon-capture-direct-air-dac-cost-analysis" target="_blank"&amp;gt;Direct Air Capture in 2026: Cost, Scale, and Path to $200/tCO2&amp;lt;/a&amp;gt; (January 2026)&amp;lt;/li&amp;gt;
                &amp;lt;li id="ref-8" data-index="8"&amp;gt;&amp;lt;strong&amp;gt;World Economic Forum:&amp;lt;/strong&amp;gt; &amp;lt;a href="https://www.weforum.org/stories/2026/01/scale-carbon-capture-storage-climate-action/" target="_blank"&amp;gt;How to scale carbon capture and storage for climate action&amp;lt;/a&amp;gt; (January 2026)&amp;lt;/li&amp;gt;
                &amp;lt;li id="ref-9" data-index="9"&amp;gt;&amp;lt;strong&amp;gt;International Energy Agency (IEA):&amp;lt;/strong&amp;gt; &amp;lt;a href="https://www.iea.org/policies/16255-inflation-reduction-act-2022-sec-13104-extension-and-modification-of-credit-for-carbon-oxide-sequestration" target="_blank"&amp;gt;Inflation Reduction Act 2022: Sec. 13104 Extension and Modification of Credit for Carbon Oxide Sequestration&amp;lt;/a&amp;gt; (February 2026)&amp;lt;/li&amp;gt;
            &amp;lt;/ul&amp;gt;
        &amp;lt;/div&amp;gt;

        &amp;lt;footer&amp;gt;
            &amp;lt;p style="text-align: center; color: var(--text-muted); font-size: 0.875rem; margin: 0;"&amp;gt;&amp;amp;copy; 2026 Carbon Capture Intelligence. Compiled June 2026.&amp;lt;/p&amp;gt;
        &amp;lt;/footer&amp;gt;
    &amp;lt;/div&amp;gt;
&amp;lt;/main&amp;gt;
&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;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
plaintext&lt;/p&gt;

&lt;p&gt;The rendered form of the report is shown here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwxvzlpo1s4xuxdkf3k0y.png" class="article-body-image-wrapper"&gt;&lt;img 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%2Fwxvzlpo1s4xuxdkf3k0y.png" width="800" height="698"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  Understanding the Two IDs
&lt;/h4&gt;

&lt;p&gt;It is important to understand the Two IDs and here is a table that breaks it down:&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%2Fjwdcek7ajrh56cqm4od2.png" class="article-body-image-wrapper"&gt;&lt;img 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%2Fjwdcek7ajrh56cqm4od2.png" width="798" height="166"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tip:&lt;/strong&gt; You can pass environment_id without previous_interaction_id to reuse the files and installed packages, but start a fresh conversation. This is useful when you want to "fork" the workspace with a new task.&lt;/p&gt;
&lt;h3&gt;
  
  
  Downloading files
&lt;/h3&gt;

&lt;p&gt;The previous section demonstrated how we can use the instruction itself to specify it to output the file content that it generated. That is one way but maybe not the way that you may want. You would probably want to download the file directly from the sandbox. Let’s do that.&lt;/p&gt;

&lt;p&gt;Shown below is the entire code listing that we saw in the previous multi-turn interaction to create markdown report and then a HTML version of it. Just that we are going to add some code at the end to download the entire environment snapshot as a tar file and then extract it in a local folder. This is currently what the Managed Agents Environment supports. Read the documentation &lt;a href="https://ai.google.dev/gemini-api/docs/agent-environment#download_files_from_the_environment" rel="noopener noreferrer"&gt;here&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;import os
import requests
import tarfile
from google import genai
client = genai.Client()

# Turn 1: Research and create a report
interaction_1 = client.interactions.create(
    agent="antigravity-preview-05-2026",
    input="Research the current state of carbon capture technology in 2026. "
          "Write a comprehensive 500-word report and save it as report.md",
    environment="remote"
)
print(f"Environment ID: {interaction_1.environment_id}")
print(f"Interaction ID: {interaction_1.id}")
print(interaction_1.output_text)

# Turn 2: Build on the previous work - same sandbox, same files
interaction_2 = client.interactions.create(
    agent="antigravity-preview-05-2026",
    environment=interaction_1.environment_id, # ← Re-attaches to same Ubuntu sandbox
    previous_interaction_id=interaction_1.id, # ← Preserves conversation memory
    input="Convert that report.md file into a clean index.html webpage "
          "with modern inline CSS styling and responsive design."
          " Please output the contents of the index.html file"
)
print(interaction_2.output_text)

env_id = interaction_2.environment_id
api_key = os.environ.get("GEMINI_API_KEY")

response = requests.get(
    f"https://generativelanguage.googleapis.com/v1beta/files/environment-{env_id}:download",
    params={"alt": "media"},
    headers={"x-goog-api-key": api_key},
    allow_redirects=True,
)

with open("snapshot_env.tar", "wb") as f:
    f.write(response.content)

os.makedirs("extracted_env_snapshot", exist_ok=True)
with tarfile.open("snapshot_env.tar") as tar:
    tar.extractall(path="extracted_env_snapshot")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
plaintext&lt;/p&gt;

&lt;p&gt;Currently, as of writing this article, there is no SDK and it is a direct REST call to get the environment snapshot.&lt;/p&gt;

&lt;p&gt;Here is the output on my local machine after I run the above program:&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%2F5g1p7ljawoc7g48819qy.png" class="article-body-image-wrapper"&gt;&lt;img 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%2F5g1p7ljawoc7g48819qy.png" width="616" height="198"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Customizing Agents: Skills, Personas, and Configuration
&lt;/h3&gt;

&lt;p&gt;Instead of cramming everything into a single prompt string, Antigravity uses a &lt;strong&gt;filesystem-native configuration system&lt;/strong&gt;. When the sandbox boots up, it automatically looks for a hidden .agents/ directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;📁 Your-Project-Directory/
└── 📁 .agents/
    ├── 📄 AGENTS.md ← Global system instructions (persona, rules, standards)
    └── 📁 skills/
        └── 📁 data-cleaner/
            └── 📄 SKILL.md ← Specific skill with step-by-step instructions
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
plaintext&lt;/p&gt;
&lt;h4&gt;
  
  
  AGENTS.md — The Agent’s Persona
&lt;/h4&gt;

&lt;p&gt;This file contains the foundational rules, behavioral guardrails, and project-specific context for your agent. Think of it as a README that the agent reads before starting any task.&lt;/p&gt;
&lt;h4&gt;
  
  
  SKILL.md — Modular Expertise
&lt;/h4&gt;

&lt;p&gt;Skills package domain-specific expertise into reusable, modular units. They use &lt;strong&gt;YAML frontmatter&lt;/strong&gt; for metadata and Markdown for instructions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;---
name: data-cleaner
description: Use when the user needs to clean, normalize, or validate tabular data files.
---
# Data Cleaner
## When to Use
- User provides CSV, Excel, or JSON files that need cleaning
- Data has missing values, inconsistent formatting, or duplicate rows
## Steps
1. Load the data file using pandas
2. Profile the data: count nulls, duplicates, and type mismatches
3. Apply cleaning rules (fill nulls, normalize strings, deduplicate)
4. Save the cleaned output and generate a summary report
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
plaintext&lt;/p&gt;

&lt;p&gt;The key insight is &lt;strong&gt;progressive disclosure&lt;/strong&gt; : the agent only loads the full content of a SKILL.md when it determines the skill is relevant to the current task. At startup, it reads only the name and description from the frontmatter, keeping the context window clean.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tip:&lt;/strong&gt; If a skill isn’t triggering when you expect it to, the issue is almost always the description in the YAML frontmatter. Make it more specific about &lt;strong&gt;when&lt;/strong&gt; the skill should activate.&lt;/p&gt;
&lt;h3&gt;
  
  
  Persistent Agent Creation
&lt;/h3&gt;

&lt;p&gt;For production use, you can register a persistent agent configuration so you don’t repeat yourself. In other words, you can create a Named Agent with the Agents API.&lt;/p&gt;

&lt;p&gt;Let’s see how to create a persistent agent using the same CSV Cleaner logic skill that we introduced in the previous section.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from google import genai

client = genai.Client()

# Register a reusable, named agent with the data-cleaner skill baked in
agent = client.agents.create(
    id="my-csv-cleaner",
    base_agent="antigravity-preview-05-2026",
    system_instruction="You are a data quality engineer. Always use pandas for data manipulation. "
                       "Always generate a before/after summary showing what changed.",
    base_environment={
        "type": "remote",
        "sources": [
            {
                "type": "inline",
                "target": ".agents/AGENTS.md",
                "content": (
                    "# Data Quality Agent\n\n"
                    "## Standards\n"
                    "- Never drop rows silently — log every removal with a reason\n"
                    "- Normalize all string columns to lowercase, stripped of whitespace\n"
                    "- Output cleaned files in UTF-8 CSV format\n"
                    "- Always print a summary table at the end\n"
                )
            },
            {
                "type": "inline",
                "target": ".agents/skills/data-cleaner/SKILL.md",
                "content": (
                    "---\n"
                    "name: data-cleaner\n"
                    "description: Use when the user needs to clean, normalize, or validate tabular data files.\n"
                    "---\n"
                    "# Data Cleaner\n\n"
                    "## When to Use\n"
                    "- User provides CSV, Excel, or JSON files that need cleaning\n"
                    "- Data has missing values, inconsistent formatting, or duplicate rows\n\n"
                    "## Steps\n"
                    "1. Load the data file using pandas\n"
                    "2. Profile the data: count nulls, duplicates, and type mismatches\n"
                    "3. Apply cleaning rules (fill nulls, normalize strings, deduplicate)\n"
                    "4. Save the cleaned output and generate a summary report\n"
                )
            }
        ]
    }
)

print(f"Agent created with ID: {agent.id}")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
python&lt;/p&gt;

&lt;p&gt;Create a file named create_csv_cleaner_agent.py with the above code and run it. This will create a persistent agent that you can refer to via its registered agent ID i.e. my-csv-cleaner.&lt;/p&gt;

&lt;p&gt;Let’s put the agent to use. First up, create a file with a few messed up customer records in a CSV file named messy_customers.csv.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;name,email,phone,country
John Smith,john@example.com,+14155551234,US
jane doe, JANE@EXAMPLE.COM ,4155559999,
John Smith,john@example.com,+14155551234,US
Bob Wilson,bob@@invalid,+442071234567,
María García,maria@test.com,+34612345678,Spain
  alice brown ,alice@example.com,,US
Charlie Lee,charlie@test.com,+61412345678,AU
jane doe,jane@example.com,+14155559999,
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
python&lt;/p&gt;

&lt;p&gt;Now you can invoke this agent by ID anywhere in your app. Create a file named run_csv_cleaner_agent.py with the content given below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from google import genai

client = genai.Client()

# Read your local CSV file
with open("messy_customers.csv", "r") as f:
    csv_content = f.read()

# Inject the file into the sandbox and tell the agent to clean it
interaction = client.interactions.create(
    agent="my-csv-cleaner",
    input="Clean the file at data/customers.csv. "
          "Remove duplicate rows by email (case-insensitive), "
          "standardize phone numbers to E.164 format, "
          "fill missing 'country' fields by looking up the phone country code, "
          "and flag any rows where the email format is invalid. "
          "Generate a before/after summary showing what changed.",
    environment={
        "type": "remote",
        "sources": [
            {
                "type": "inline",
                "target": "data/customers.csv", # ← Path inside the sandbox
                "content": csv_content # ← Your local file contents
            }
        ]
    }
)

print(interaction.output_text)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
python&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What’s happening in the above code:&lt;/strong&gt; The sources array pre-loads files into the sandbox &lt;em&gt;before&lt;/em&gt; the agent starts working. The agent sees data/customers.csv as a real file in its Linux filesystem — it doesn't know or care that you injected it from your local machine. This works for any file type: CSV, JSON, XML, Python scripts, config files, etc.&lt;/p&gt;

&lt;p&gt;Notice how the prompt doesn’t mention pandas, UTF-8, or logging rules — all of that is already encoded in the AGENTS.md and SKILL.md that the named agent carries with it. The data-cleaner skill activates automatically because the task description matches the skill's description field.&lt;/p&gt;

&lt;p&gt;A sample run of the above file is shown below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;I have successfully cleaned the customer dataset at `data/customers.csv` using Python and `pandas`. 

Below is a detailed report and before/after summary of the transformations applied.

---

### Summary of Transformations

1. **whitespace Trimming:** Stripped all leading and trailing whitespace from both column names and text values (e.g., ` alice brown ` became `alice brown`).
2. **Email Normalization &amp;amp; Validation:** 
   - Converted all email addresses to lowercase and trimmed whitespace.
   - Added a new column `email_invalid` (boolean) to flag emails with an invalid format.
   - Identified `bob@@invalid` as an invalid format (due to a duplicate `@` symbol and lack of a top-level domain).
3. **Phone Number Standardization:**
   - Standardized all valid phone numbers to the international **E.164** format using the `phonenumbers` library.
   - Converted `4155559999` (with a default US region fallback) to `+14155559999`.
   - Ignored the missing phone number for `alice brown` while leaving it empty.
4. **Country Code Lookup:**
   - Looked up and populated missing `country` values based on the telephone country code prefix.
   - Filled `jane doe`'s country as `US` (derived from prefix `+1`).
   - Filled `Bob Wilson`'s country as `GB` (derived from prefix `+44`).
   - Kept existing valid country entries (e.g., `Spain`, `US`, `AU`) intact.
5. **Deduplication:**
   - Removed duplicate rows by performing a case-insensitive match on the cleaned `email` column, keeping the first occurrence.
   - Safely removed the duplicate row for `john@example.com` (Row 3).
   - Safely removed the duplicate row for `jane@example.com` (Row 8).

---

### Before/After Summary

#### 1. Data Quality Metrics

| Metric | Before Clean | After Clean | Change Description |
| :--- | :---: | :---: | :--- |
| **Total Rows** | 8 | 6 | 2 duplicate rows were removed. |
| **Duplicates Removed** | 0 | 2 | Dropped rows 3 (`john@example.com`) and 8 (`jane@example.com`). |
| **Invalid Emails Flagged** | 0 | 1 | Flagged `bob@@invalid` as invalid (`email_invalid = True`). |
| **Standardized Phone Numbers** | 1 | 5 | All numbers formatted to E.164 (e.g., `4155559999` -&amp;gt; `+14155559999`). |
| **Filled Country Fields** | 5 | 6 | Filled 2 missing country values (`US` and `GB`) via phone prefix lookups. |

#### 2. Row-by-Row Comparison

Below is the row-by-row evolution from the raw file to the cleaned output:

| Row # | Name (Before) | Name (After) | Email (Before) | Email (After) | Phone (Before) | Phone (After) | Country (Before) | Country (After) | Email Invalid Flag | Action Taken / Status |
| :---: | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :---: | :--- |
| **1** | `John Smith` | `John Smith` | `john@example.com` | `john@example.com` | `+14155551234` | `+14155551234` | `US` | `US` | `False` | Retained as first unique instance. |
| **2** | `jane doe` | `jane doe` | ` JANE@EXAMPLE.COM ` | `jane@example.com` | `4155559999` | `+14155559999` | *Missing* | `US` | `False` | Email normalized; Phone formatted to E.164; Country populated from `+1` prefix. |
| **3** | `John Smith` | — | `john@example.com` | — | `+14155551234` | — | `US` | — | — | **Removed** (Duplicate email). |
| **4** | `Bob Wilson` | `Bob Wilson` | `bob@@invalid` | `bob@@invalid` | `+442071234567` | `+442071234567` | *Missing* | `GB` | `True` | Country populated from `+44` prefix; Email flagged as invalid. |
| **5** | `María García` | `María García` | `maria@test.com` | `maria@test.com` | `+34612345678` | `+34612345678` | `Spain` | `Spain` | `False` | Retained; Email valid; Preserved existing country. |
| **6** | ` alice brown ` | `alice brown` | `alice@example.com` | `alice@example.com` | *Missing* | *Missing* | `US` | `US` | `False` | Name whitespace stripped; Phone left empty; Preserved existing country. |
| **7** | `Charlie Lee` | `Charlie Lee` | `charlie@test.com` | `charlie@test.com` | `+61412345678` | `+61412345678` | `AU` | `AU` | `False` | Retained; Email valid. |
| **8** | `jane doe` | — | `jane@example.com` | — | `+14155559999` | — | *Missing* | — | — | **Removed** (Duplicate email). |

---

### Cleaned Dataset Output

The cleaned data has been written back to `data/customers.csv` and contains the following records:

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
csv&lt;br&gt;
name,email,phone,country,email_invalid&lt;br&gt;
John Smith,&lt;a href="mailto:john@example.com"&gt;john@example.com&lt;/a&gt;,+14155551234,US,False&lt;br&gt;
jane doe,&lt;a href="mailto:jane@example.com"&gt;jane@example.com&lt;/a&gt;,+14155559999,US,False&lt;br&gt;
Bob Wilson,bob@@invalid,+442071234567,GB,True&lt;br&gt;
María García,&lt;a href="mailto:maria@test.com"&gt;maria@test.com&lt;/a&gt;,+34612345678,Spain,False&lt;br&gt;
alice brown,&lt;a href="mailto:alice@example.com"&gt;alice@example.com&lt;/a&gt;,,US,False&lt;br&gt;
Charlie Lee,&lt;a href="mailto:charlie@test.com"&gt;charlie@test.com&lt;/a&gt;,+61412345678,AU,False&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
plaintext&lt;/p&gt;
&lt;h3&gt;
  
  
  Building Real-World Agents: A few Use Cases
&lt;/h3&gt;

&lt;p&gt;Now that you understand the foundations, let’s build a few agents. Each one introduces new capabilities and patterns.&lt;/p&gt;
&lt;h3&gt;
  
  
  Use Case 1: Automated Code Refactoring &amp;amp; Test Fixing
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The Problem:&lt;/strong&gt; You have a Python project with outdated code and failing tests. A standard LLM gives you code snippets, but you still have to manually copy, paste, run tests, debug, and iterate.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Antigravity Solution:&lt;/strong&gt; The agent clones your code, runs the test suite, reads terminal errors, patches the code, and re-runs tests — looping until everything passes.&lt;/p&gt;

&lt;p&gt;We are providing a repository here with buggy code. Take a look:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/rominirani/uc1-legacy-app" rel="noopener noreferrer"&gt;GitHub - rominirani/uc1-legacy-app: Managed Agents Sample App Repository with Bugs&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  Known Bugs to fix for the Agent
&lt;/h4&gt;

&lt;p&gt;As per the repository and you can take a look at it too, there are 3 root-cause bugs across the codebase (causing 6 test failures):&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;utils.py — calculate_total() does arithmetic on a string tax_rate without converting to float.&lt;/li&gt;
&lt;li&gt;utils.py — normalize_name() crashes on None input (no null check).&lt;/li&gt;
&lt;li&gt;models.py — Invoice.summary() references self.total (method object) instead of self.total() (method call).&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;
  
  
  The Code
&lt;/h3&gt;

&lt;p&gt;Let’s write our Agent that can fix this for us. Check out the instruction in detail below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from google import genai
client = genai.Client()

system_instructions = """
You are an expert QA and Refactoring Engineer. Your workflow is:
1. Clone the target repository into the workspace
2. Install all dependencies from requirements.txt
3. Run the full pytest suite and capture all output
4. For each failing test:
   a. Read the error traceback carefully
   b. Open the source file causing the failure
   c. Diagnose the root cause
   d. Apply the minimal fix
5. Re-run pytest after each fix to confirm resolution
6. Continue until ALL tests pass (0 failures)
7. Generate a summary of every change you made
IMPORTANT: Make the minimal possible change to fix each test.
Do not refactor working code unnecessarily.
"""
interaction = client.interactions.create(
    agent="antigravity-preview-05-2026",
    system_instruction=system_instructions,
    input="""
    Clone this repository: https://github.com/rominirani/uc1-legacy-app
    Run the pytest suite to check for environment or code failures.
    Isolate the bugs causing test failures and fix them one by one.
    Keep running the tests until you achieve a 100% pass rate.
    When done, provide:
    1. A list of all files modified with a diff summary
    2. The final pytest output showing all tests passing
    3. Any dependency changes you had to make
    """,
    environment="remote"
)
print(interaction.output_text)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
plaintext&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Run it:&lt;/strong&gt; Save the above as uc1_refactor.py and run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;python3 uc1_refactor.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
shell&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Expected output:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;I have successfully diagnosed and resolved all the issues causing test failures in the `uc1-legacy-app` repository. Below is a detailed summary of the findings, modifications, and the final test execution output.

---

### 1. Modified Files &amp;amp; Diff Summary

#### File: `src/models.py`
- **Issue** : In the `Invoice.summary()` method, the `self.total` method itself was passed to `format_currency()` as an object, instead of being invoked (`self.total()`). This led to a `TypeError` during format evaluation.
- **Fix** : Changed `self.total` to `self.total()`.
- **Diff Summary** :
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
diff&lt;br&gt;
@@ -23,7 +23,7 @@ class Invoice:&lt;br&gt;
"""Return a one-line summary of the invoice."""&lt;br&gt;
from src.utils import format_currency, normalize_name&lt;br&gt;
name = normalize_name(self.customer_name)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;return f"Invoice {self.invoice_id}: {name} - {format_currency(self.total)}"&lt;/li&gt;
&lt;li&gt;return f"Invoice {self.invoice_id}: {name} - {format_currency(self.total())}"
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
#### File: `src/utils.py`
- **Issues** :
1. **`calculate_total()`**: When `tax_rate` is received as a string, Python fails to perform multiplication of float/string (`TypeError: can't multiply sequence by non-int of type 'float'`).
2. **`normalize_name()`**: When passed a `None` value (common in CSV imports), the code raised `AttributeError: 'NoneType' object has no attribute 'strip'`.
- **Fixes** :
1. Explicitly cast `subtotal` and `tax_rate` to `float` prior to calculating the tax.
2. Add a safeguard to return an empty string (`""`) when `name` is `None`.
- **Diff Summary** :
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;br&gt;
diff&lt;br&gt;
@@ -11,8 +11,10 @@ def calculate_total(subtotal, tax_rate):&lt;br&gt;
Returns:&lt;br&gt;
The total as a float rounded to 2 decimal places.&lt;br&gt;
"""&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;tax = subtotal * tax_rate / 100&lt;/li&gt;
&lt;li&gt;return round(subtotal + tax, 2)&lt;/li&gt;
&lt;li&gt;subtotal_val = float(subtotal)&lt;/li&gt;
&lt;li&gt;tax_rate_val = float(tax_rate)&lt;/li&gt;
&lt;li&gt;tax = subtotal_val * tax_rate_val / 100&lt;/li&gt;
&lt;li&gt;return round(subtotal_val + tax, 2)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;def format_currency(amount):&lt;br&gt;
@@ -36,6 +38,8 @@ def normalize_name(name):&lt;br&gt;
Returns:&lt;br&gt;
Cleaned, title-cased name.&lt;br&gt;
"""&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;if name is None:&lt;/li&gt;
&lt;li&gt;return ""
return name.strip().title()
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
---

### 2. Dependency Changes
No additional packages or dependency changes were made. All required libraries from `requirements.txt` (consisting of `pytest&amp;gt;=7.0.0`) were successfully installed and utilized without modification.

---

### 3. Final Pytest Output
Running the full suite confirms that all 10 tests now pass:

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;br&gt;
plaintext&lt;br&gt;
============================= test session starts ==============================&lt;br&gt;
platform linux -- Python 3.12.3, pytest-9.0.3, pluggy-1.6.0&lt;br&gt;
rootdir: /uc1-legacy-app&lt;br&gt;
plugins: anyio-4.13.0&lt;br&gt;
collected 10 items&lt;/p&gt;

&lt;p&gt;tests/test_models.py .... [40%]&lt;br&gt;
tests/test_utils.py ...... [100%]&lt;/p&gt;

&lt;p&gt;============================== 10 passed in 0.02s ==============================&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
plaintext&lt;/p&gt;
&lt;h3&gt;
  
  
  What Happens Behind the Scenes
&lt;/h3&gt;

&lt;p&gt;The agent autonomously:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Runs git clone in the sandbox terminal&lt;/li&gt;
&lt;li&gt;Runs pip install -r requirements.txt (installing into the sandbox's Python)&lt;/li&gt;
&lt;li&gt;Runs pytest -v and reads the full output, including tracebacks&lt;/li&gt;
&lt;li&gt;Opens the failing source files, identifies buggy logic&lt;/li&gt;
&lt;li&gt;Writes patches, saves files, re-runs pytest&lt;/li&gt;
&lt;li&gt;Loops until the output shows 0 failures&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Key Concept Introduced:&lt;/strong&gt; The &lt;strong&gt;Plan → Act → Observe&lt;/strong&gt; loop in action. The agent doesn’t just generate code — it executes, reads real terminal output, and self-corrects.&lt;/p&gt;
&lt;h3&gt;
  
  
  Use Case 2: Live Competitive Intelligence Engine
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The Problem:&lt;/strong&gt; You need a deep competitive analysis of rival products. Manual web scraping is tedious, and static scrapers break constantly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Antigravity Solution:&lt;/strong&gt; The agent uses its web browsing tools to search Google, crawls competitor websites, dynamically adapts to different page structures, writes a custom pandas script to structure the data, and exports a polished spreadsheet.&lt;/p&gt;
&lt;h3&gt;
  
  
  The Code
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from google import genai
client = genai.Client()

system_instructions = """
You are a precise Business Intelligence Analyst. Your workflow:
1. Use web search to find current, real-time information
2. Navigate to official product/pricing pages for each competitor
3. Extract: pricing tiers, key features, target audience, notable limitations
4. Structure ALL findings into a pandas DataFrame
5. Export to both CSV and a formatted Markdown comparison table
6. Include the date/time of research and source URLs for every data point
Rules:
- Only report data you can verify from official sources
- If pricing isn't publicly available, note "Contact Sales" - don't guess
- Use USD for all pricing normalization
"""
interaction = client.interactions.create(
    agent="antigravity-preview-05-2026",
    system_instruction=system_instructions,
    input="""
    Research the pricing models and core feature matrices of the top 3 alternative
    platforms to Vercel for frontend deployment:
    1. Netlify
    2. Cloudflare Pages
    3. Cloud Run
    For each, extract:
    - Free tier limits (bandwidth, builds, sites)
    - Pro/paid tier pricing and what it unlocks
    - Key differentiating features
    - Notable limitations or complaints from developer communities
    Create:
    1. A competitive_matrix.csv spreadsheet with all data
    2. A competitive_analysis.md report with a formatted comparison table
       and a "Recommendation" section at the bottom
    """,
    environment="remote"
)
print(interaction.output_text)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;br&gt;
python&lt;/p&gt;

&lt;p&gt;This produces the following output (a lovely report).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;As a Business Intelligence Analyst, I have conducted a precise competitive analysis of the top three frontend deployment alternatives to Vercel: **Netlify** , **Cloudflare Pages** , and **Google Cloud Run**.

All findings have been structured using `pandas` and exported to `/` (the current working directory) as:
1. `competitive_matrix.csv` — The raw, structured dataset.
2. `competitive_analysis.md` — A comprehensive, reader-ready report including a detailed markdown comparison matrix, architectural breakdowns, limitation analyses, and a tailored recommendation framework.

All data has been verified against official vendor pricing, product, and developer documentation as of **June 9, 2026**. All currency values are normalized in **USD**.

---

### Core Finding Highlights

#### 1. Netlify
* **The Architectural Shift (April 2026):** Netlify made a massive strategic update to its Pro plans, moving from a seat-based model ($19/member/month) to a **flat $20/month per organization** [10]. This includes unlimited team members (Owners, Developers, Reviewers, and Git Contributors) [10], which is highly disruptive compared to Vercel's strict per-seat billing.
* **The Credits Trap:** Usage is now managed entirely via a unified credit-based model (300 credits/mo free, 3,000 on Pro) [2, 10]. However, credits are consumed fast: bandwidth costs 20 credits per GB [2, 10] (meaning Free tier is only **~15 GB max** and Pro is only **~150 GB max** if solely used for traffic). If Free tier credits run out, **all site traffic pauses immediately** (no auto-recharge is supported on Free) [2, 11]. 
* **Capabilities:** Highly integrated features like Netlify Database (managed Postgres via Neon) [4], Blob storage, Forms, and Auth [10]. Serverless timeout is 10s on Free/Personal [2] and 26s on Pro [2].

#### 2. Cloudflare Pages
* **Unmetered Freedom:** Genuinely **unlimited and unmetered static bandwidth and requests** across all tiers (including the $0 Free tier) [24, 25, 27].
* **The Pro Tier ($20/mo billed annually / $25/mo monthly):** Tied directly to Cloudflare's Workers Paid plan [25, 27]. It increases build limits from 500/mo to 5,000/mo, concurrent builds from 1 to 5, and the file-count ceiling per project from 20,000 to 100,000 assets [31] (unlocked via the `PAGES_WRANGLER_MAJOR_VERSION=4` env variable) [31].
* **Edge Isolates Constraints:** While running serverless code on Cloudflare's global network of 310+ cities is blazingly fast with zero cold starts [24, 33], it uses a **strict V8 edge runtime** [24]. Standard Node.js library modules (`fs`, `path`, native `crypto`) do not run natively [24], forcing developers to compile meta-frameworks like Next.js via edge adapters (e.g., `@cloudflare/next-on-pages` or OpenNext) [24] which restricts certain features like Incremental Static Regeneration (ISR).

#### 3. Google Cloud Run
* **Pure Container Portability:** Cloud Run runs any application, language, or compiled binary (Node.js, Python, Go, Rust) packaged in a standard Docker container [37, 39]. It runs full Node.js natively [39], ensuring 100% Next.js feature parity (ISR, Server Actions, dynamic image optimization) with zero edge-runtime workarounds [39].
* **No Monthly Base Fee:** Operates on a pure pay-as-you-go serverless model (billed in granular vCPU-seconds and GiB-seconds) [41], backed by a generous Always Free tier (2 million requests/mo, 180,000 vCPU-seconds, 360,000 GiB-seconds, and 120 daily Cloud Build minutes free) [37, 38, 41]. 
* **The Infrastructure Overhead:** Not a standard "push-to-deploy" platform. Developers must write Dockerfiles, configure Artifact Registry, and manage IAM and networking [37, 39]. It is regionally hosted; to get a global CDN with SSL mapping, you must set up Cloud CDN and a Global HTTP Load Balancer [37] (~$20-$30/mo base fee) and navigate container cold starts (2 to 10+ seconds) [37] and expensive internet egress rates ($0.085 - $0.12 per GB) [37].

---

### Structure of Generated Files

#### 1. `competitive_matrix.csv`
A raw, tabular CSV structured for business intelligence pipelines, featuring the following schema:
- `Platform Name`
- `Free Tier Pricing (USD)`
- `Free Tier Bandwidth Limit`
- `Free Tier Build Limit`
- `Free Tier Sites/Projects Limit`
- `Free Tier Key Specs &amp;amp; Features`
- `Paid/Pro Tier Price (USD)`
- `Paid/Pro Tier Features Unlocked`
- `Key Differentiating Features`
- `Notable Limitations &amp;amp; Developer Complaints`
- `Date of Research`
- `Source URLs`

#### 2. `competitive_analysis.md`
A professionally formatted report including:
* **Executive Summary:** Contextualizing why frontend teams are exploring alternatives to Vercel in 2026.
* **Structured Comparison Table:** Transposed for high-density reading and side-by-side comparison.
* **Deep-Dive Section:** Dedicated analyses of the Free limits, paid features, unique differentiators, and community complaints for Netlify, Cloudflare Pages, and Google Cloud Run.
* **Architectural Recommendation Flowchart &amp;amp; Matrix:** Tailored decision pathways based on project profile:
  * *Static / JAMstack / Zero-Budget* $\rightarrow$ **Cloudflare Pages**
  * *Collaborative Teams / Rapid Prototyping / Seat-Free DX* $\rightarrow$ **Netlify**
  * *Complex Server-Side Rendering / Backend Pipelines / Custom Docker* $\rightarrow$ **Google Cloud Run**

---

### Source Verification &amp;amp; Citations

1. **Netlify:**
   - [Official Pricing &amp;amp; Plans](https://www.netlify.com/pricing/)
   - [Introducing Seat-Free Collaborative Billing (April 14, 2026)](https://www.netlify.com/blog/pricing-netlify-for-3-billion-builders/)
   - [Credit-Based Pricing Documentation](https://docs.netlify.com/manage/accounts-and-billing/billing/billing-for-credit-based-plans/credit-based-pricing-plans/)
   - [Netlify Free Tier Credit Analysis (Temps)](https://temps.sh/compare/vs-netlify)

2. **Cloudflare Pages:**
   - [Workers &amp;amp; Pages Pricing Matrix](https://www.cloudflare.com/plans/developer-platform/)
   - [Official Pages Limits Documentation](https://developers.cloudflare.com/pages/platform/limits/)
   - [Cloudflare Pages Platform Features](https://pages.cloudflare.com/)
   - [Cloudflare Pages Edge Limitations (Temps)](https://temps.sh/compare/vs-cloudflare-pages)

3. **Google Cloud Run:**
   - [Official Cloud Run Pricing Breakdown](https://cloud.google.com/run/pricing)
   - [Google Cloud Free Tier Inclusions](https://cloud.google.com/free)
   - [Cloud Run Quotas &amp;amp; Limits](https://docs.cloud.google.com/run/quotas)
   - [Cloud Run Cost Optimization &amp;amp; Egress Guide (Cloudchipr)](https://cloudchipr.com/blog/cloud-run-pricing)

The generated files are saved directly in your working directory and are immediately available for download or integration into your reporting pipelines. Let me know if you would like me to modify the analysis parameters or explore a specific platform further!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
plaintext&lt;/p&gt;
&lt;h4&gt;
  
  
  Building on the Analysis (Multi-Turn)
&lt;/h4&gt;

&lt;p&gt;You can do a follow up too, by using the previous environment and interaction to take the competitive_matrix.csv generated and creating some visualization out of it. While the code below retrieves only the text output, you can use the technique shown below to &lt;strong&gt;download&lt;/strong&gt; the environment sandbox and extract out the files generated.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Follow-up: generate a visual chart from the data we just collected
interaction_2 = client.interactions.create(
    agent="antigravity-preview-05-2026",
    environment=interaction.environment_id,
    previous_interaction_id=interaction.id,
    input="""
    Using the competitive_matrix.csv you just created:
    1. Create a grouped bar chart comparing the free tier limits across all 3 platforms
    2. Create a pricing comparison chart for the paid tiers
    3. Save both charts as PNG files with clear labels and a professional color scheme
    4. Add the charts as embedded images in the competitive_analysis.md report
    """
)
print(interaction_2.output_text)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
python&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Concepts Introduced:&lt;/strong&gt;  &lt;strong&gt;Web browsing&lt;/strong&gt; + &lt;strong&gt;code execution&lt;/strong&gt; in the same task. The agent searches the live internet, then writes Python code to structure and visualize the data — all in one flow.&lt;/p&gt;
&lt;h3&gt;
  
  
  More Use Cases
&lt;/h3&gt;

&lt;p&gt;I plan to keep adding to this document with more use cases, as this solution matures with more features. Stay tuned for updates.&lt;/p&gt;
&lt;h3&gt;
  
  
  Best Practices
&lt;/h3&gt;

&lt;p&gt;Here are the architectural patterns that will serve you well in production:&lt;/p&gt;
&lt;h4&gt;
  
  
  Build to Delete
&lt;/h4&gt;

&lt;p&gt;Model performance improves rapidly. Design your agents with the expectation that they’ll be rebuilt with newer models soon. Keep configurations modular — AGENTS.md + SKILL.md files are easy to swap. Don't over-engineer the orchestration layer.&lt;/p&gt;
&lt;h4&gt;
  
  
  Treat Agents as Microservices
&lt;/h4&gt;

&lt;p&gt;Don’t build one massive agent with a 2,000-word system prompt. Decompose complex problems into specialized sub-agents:&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%2Fl567wtzicxuvrr78nc9a.png" class="article-body-image-wrapper"&gt;&lt;img 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%2Fl567wtzicxuvrr78nc9a.png" width="800" height="264"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  Errors as Inputs, Not Crashes
&lt;/h4&gt;

&lt;p&gt;In robust agentic architectures, errors are data and are inputs for the agent to self-reflect and correct. The agent reads a TypeError, reasons about the cause, and fixes it. Don't wrap everything in try/except blocks that swallow errors. Let the agent see them.&lt;/p&gt;
&lt;h4&gt;
  
  
  Evals Over Unit Tests
&lt;/h4&gt;

&lt;p&gt;Agent behavior is non-deterministic. Testing focuses on &lt;strong&gt;evaluation metrics&lt;/strong&gt; rather than exact output matching:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
# ❌ Don't: Assert exact output
assert agent_output == "The answer is 42"

# ✅ Do: Evaluate behavioral success rate
results = [run_agent(task) for _ in range(20)]
success_rate = sum(1 for r in results if r.meets_criteria) / len(results)
assert success_rate &amp;gt;= 0.85 # Agent succeeds at least 85% of the time
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Token Cost Awareness
&lt;/h4&gt;

&lt;p&gt;Because Antigravity operates an autonomous reasoning loop, a single prompt can trigger many internal operations. Expect something around this ball park:&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%2Fxj62hspmnw0o38up1o47.png" class="article-body-image-wrapper"&gt;&lt;img 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%2Fxj62hspmnw0o38up1o47.png" width="800" height="230"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Implement strict timeouts and monitor trace lengths during development. Use system_instruction to tell the agent to be concise when you don't need verbose reasoning.&lt;/p&gt;

&lt;h4&gt;
  
  
  Error Handling Patterns
&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.amazonaws.com%2Fuploads%2Farticles%2F8fq7z978oopv7evj240j.png" class="article-body-image-wrapper"&gt;&lt;img 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%2F8fq7z978oopv7evj240j.png" width="800" height="202"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Resources
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Official Documentation:&lt;/strong&gt; &lt;a href="https://ai.google.dev/gemini-api/docs/custom-agents" rel="noopener noreferrer"&gt;ai.google.dev/gemini-api/docs/custom-agents&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gemini Managed Agents: Developer Guide&lt;/strong&gt;  : &lt;a href="https://www.philschmid.de/gemini-managed-agents-developer-guide" rel="noopener noreferrer"&gt;https://www.philschmid.de/gemini-managed-agents-developer-guide&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Video: Managed Agents Deep Dive:&lt;/strong&gt; &lt;a href="https://www.youtube.com/watch?v=Psa8mLikdag" rel="noopener noreferrer"&gt;youtube.com/watch?v=Psa8mLikdag&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Video: Getting Started Tutorial:&lt;/strong&gt; &lt;a href="https://www.youtube.com/watch?v=0YXe7u-i1qU" rel="noopener noreferrer"&gt;youtube.com/watch?v=0YXe7u-i1qU&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Google AI Studio:&lt;/strong&gt; &lt;a href="https://aistudio.google.com" rel="noopener noreferrer"&gt;aistudio.google.com&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Ideas for Your Next Agent
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;CI/CD Pipeline Agent&lt;/strong&gt;  — monitors your GitHub repo, runs tests on every push, opens fix PRs for failures&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Documentation Generator&lt;/strong&gt;  — reads your codebase and generates comprehensive API docs&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data Pipeline Orchestrator&lt;/strong&gt;  — connects to your warehouse, runs transformations, validates output&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Customer Support Triage Agent&lt;/strong&gt;  — reads tickets, categorizes severity, drafts responses, escalates critical issues&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Research Assistant&lt;/strong&gt;  — takes a topic, searches papers and articles, writes a literature review with citations&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Final Thought
&lt;/h3&gt;

&lt;p&gt;Managed Agents represent a fundamental shift in how we build with AI. You’re no longer building the infrastructure around the AI, you’re simply giving the AI a goal and a sandbox, and letting it work. The sandbox is the abstraction. The agentic loop is the engine. And the Interactions API is your single point of contact with all of it.&lt;/p&gt;

&lt;p&gt;Most importantly, start small and set limits on what the agent can do autonomously. Then scale up.&lt;/p&gt;

&lt;p&gt;Happy building.&lt;/p&gt;




</description>
      <category>agentsasanapi</category>
      <category>managedagent</category>
      <category>gemini</category>
      <category>managedagentsapi</category>
    </item>
    <item>
      <title>Google Cloud Platform Technology Nuggets — May 16–31, 2026</title>
      <dc:creator>Romin Irani</dc:creator>
      <pubDate>Wed, 03 Jun 2026 06:19:11 +0000</pubDate>
      <link>https://dev.to/iromin/google-cloud-platform-technology-nuggets-may-16-31-2026-2aad</link>
      <guid>https://dev.to/iromin/google-cloud-platform-technology-nuggets-may-16-31-2026-2aad</guid>
      <description>&lt;p&gt;Welcome to the May 16–31, 2026 edition of Google Cloud Platform Technology Nuggets. The nuggets are also available on &lt;a href="https://www.youtube.com/playlist?list=PLiW95NS9M7-YaTpO0xL-ICabJvyolU-_s" rel="noopener noreferrer"&gt;YouTube&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.amazonaws.com%2Fuploads%2Farticles%2Fyijx1rw1zz59mc0uq2jd.png" class="article-body-image-wrapper"&gt;&lt;img 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%2Fyijx1rw1zz59mc0uq2jd.png" width="800" height="447"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Infographic for the post generated by NotebookLM&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  AI and Machine Learning
&lt;/h3&gt;

&lt;p&gt;If you are looking to stay updated on the latest Google Cloud AI tools, you should bookmark this &lt;a href="https://cloud.google.com/blog/products/ai-machine-learning/what-google-cloud-announced-in-ai-this-month" rel="noopener noreferrer"&gt;link&lt;/a&gt; that covers updates made across the months.&lt;/p&gt;

&lt;p&gt;There has been a spate of announcements at Google Cloud Next 2026 in April and Google I/O held in May introduced several other releases too, that included:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Gemini 3.5 Flash models&lt;/li&gt;
&lt;li&gt;Gemini Omni (any output from any input, starting with video)&lt;/li&gt;
&lt;li&gt;Google Antigravity in its new version&lt;/li&gt;
&lt;li&gt;Managed Agents on Agent Platform&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Check out the &lt;a href="https://cloud.google.com/blog/products/ai-machine-learning/innovations-from-google-io-26-on-google-cloud" rel="noopener noreferrer"&gt;post&lt;/a&gt; that highlights these announcements in detail.&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%2Fhblmt77pifq19pz0rabs.png" class="article-body-image-wrapper"&gt;&lt;img 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%2Fhblmt77pifq19pz0rabs.png" width="799" height="516"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Google Cloud has &lt;a href="https://cloud.google.com/blog/products/ai-machine-learning/nano-banana-2-and-nano-banana-pro-are-generally-available" rel="noopener noreferrer"&gt;introduced&lt;/a&gt; the general availability of Nano Banana 2 (Gemini 3.1 Flash Image) and Nano Banana Pro (Gemini 3 Pro Image) on the Gemini Enterprise Agent Platform and the Gemini API. These enterprise-grade models allow developers to integrate image generation and editing capabilities directly into their applications and workflows.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F22sz85oilx5c527yxk9a.png" class="article-body-image-wrapper"&gt;&lt;img 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%2F22sz85oilx5c527yxk9a.png" width="800" height="399"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Long-running agent workflows is where the industry is moving. But how to manage and operate them reliably and efficiently. Google believes you can use Agent Executor, an open-source runtime standard designed for executing, resuming, and deploying distributed AI agents. The key technical capabilities of this standard include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Durable execution to automatically resume progress via event logs and snapshotting after human-in-the-loop steps or outages&lt;/li&gt;
&lt;li&gt;Secure isolation through sandboxes to safely execute code and manage multi-tenant workloads&lt;/li&gt;
&lt;li&gt;Session consistency using a single-writer architecture to prevent state corruption&lt;/li&gt;
&lt;li&gt;Connection recovery to allow disconnected clients to reconnect and backfill missed responses&lt;/li&gt;
&lt;li&gt;Trajectory branching to let agents test alternative decision paths using checkpoints.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsf0lcv62mgssb8jzpsj9.png" class="article-body-image-wrapper"&gt;&lt;img 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%2Fsf0lcv62mgssb8jzpsj9.png" width="652" height="656"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Check out the &lt;a href="https://cloud.google.com/blog/products/ai-machine-learning/agent-executor-googles-distributed-agent-runtime" rel="noopener noreferrer"&gt;blog post&lt;/a&gt; for more details.&lt;/p&gt;

&lt;p&gt;Looking to deploy and optimize large language models on mobile devices, take a look at new benchmarking and debugging capabilities within the Google AI Edge Portal. The platform allows developers to run automated testing across a fleet of over 120 Android device types to evaluate performance across CPU and GPU backends using the LiteRT-LM format. Check out the &lt;a href="https://cloud.google.com/blog/products/ai-machine-learning/benchmark-llms-on-device-with-ai-edge-portal" rel="noopener noreferrer"&gt;blog post&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.amazonaws.com%2Fuploads%2Farticles%2Fr5884zde3pknm7vuna3b.png" class="article-body-image-wrapper"&gt;&lt;img 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%2Fr5884zde3pknm7vuna3b.png" width="800" height="464"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Data Analytics
&lt;/h3&gt;

&lt;p&gt;Data Agent Kit is an open-source collection of data engineering and data science skills, Model Context Protocol (MCP) tools, and plugins designed to connect development environments like VS Code and various CLIs with enterprise data. The kit provides pre-codified skills for tasks like query optimization, data validation, and troubleshooting, alongside MCP tools that create secure connections to platforms like BigQuery, AlloyDB, and Google Cloud Storage without requiring manual pipeline code. Check it out.&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%2F5io7qov3i1czge50bdaj.png" class="article-body-image-wrapper"&gt;&lt;img 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%2F5io7qov3i1czge50bdaj.png" width="800" height="478"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Remote Model Context Protocol (MCP) Server for &lt;a href="https://cloud.google.com/products/alloydb?e=13802955" rel="noopener noreferrer"&gt;AlloyDB&lt;/a&gt; is now in General Availability. The Remote MCP Server for AlloyDB runs on fully-managed Google Cloud infrastructure and exposes an HTTP endpoint that connects your AI applications to your data. It is integrated with the Agent Registry, supports fine-grained authorization, allows agents to not just run queries but also manage instances and more. Check out the &lt;a href="https://cloud.google.com/blog/products/data-analytics/alloydb-remote-mcp-server-ga-secure-ai-agent-access-to-your-data" rel="noopener noreferrer"&gt;blog post&lt;/a&gt; that highlights the features and a demo of how an agent has been integrate to work with AlloyDB.&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%2F37sga6goep7t8dnscne3.png" class="article-body-image-wrapper"&gt;&lt;img 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%2F37sga6goep7t8dnscne3.png" width="800" height="462"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Connected Sheets, which provides a direct connection between Google Sheets and BigQuery, has been there for a while. Instead of exporting data as CSVs, which causes version control and security risks, this feature allows users to perform ad-hoc analysis, modeling, and reporting on live data without writing SQL. Check out a &lt;a href="https://cloud.google.com/blog/products/data-analytics/using-connected-sheets-to-analyze-bigquery-data" rel="noopener noreferrer"&gt;blog post&lt;/a&gt;, which gives you a quick overview of Connected Sheets, walk through real-world use cases, and show you how to perform enterprise-grade data analysis using BigQuery directly in Google Sheets.&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%2F3qo6rqm8o05is3shtlr1.png" class="article-body-image-wrapper"&gt;&lt;img 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%2F3qo6rqm8o05is3shtlr1.png" width="800" height="523"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Databases
&lt;/h3&gt;

&lt;p&gt;AlloyDB has got a significant upgrade to its High Availability (HA) architecture: Hot Standby. With the new architecture, the standby node continuously streams and applies write-ahead logs (WAL) from the primary node. This change allows the system to detect failures and promote the standby node within 30 seconds, dropping the average failover time to approximately 15 seconds. Furthermore, because the standby node constantly replays logs, its memory caches stay warm, allowing the database to maintain its transaction-per-second rate immediately after a failover without any performance brownouts. This feature is automatically rolled out to new instances on PostgreSQL 18 at no additional cost, with earlier versions receiving support in the following months. For more details, check out the &lt;a href="https://cloud.google.com/blog/products/databases/alloydb-hot-standby-faster-failovers-and-consistent-performance" rel="noopener noreferrer"&gt;blog post&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.amazonaws.com%2Fuploads%2Farticles%2Fe2uean75efa3f1h9x822.png" class="article-body-image-wrapper"&gt;&lt;img 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%2Fe2uean75efa3f1h9x822.png" width="799" height="381"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Developers &amp;amp; Practitioners
&lt;/h3&gt;

&lt;p&gt;You are a developer working on building out Agents on Google technologies. How do you know which one to pick to develop these agents, since there are quite a few ranging from no-code to heavily code-driven frameworks. The &lt;a href="https://cloud.google.com/blog/topics/developers-practitioners/io26-news-for-agent-developers-on-google-cloud" rel="noopener noreferrer"&gt;article&lt;/a&gt; is an excellent way to step back and look at the existing landscape today to develop agents on Google Cloud, with options ranging from low code (Agent Studio) to ADK 2.0. Included in the spectrum is the recently announced Managed Agents API, which allows you to define agentic behavior and let Google Cloud handle the heavy lifting, acting as an agent-as-a-service with nothing to manage.&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%2Fupuejtklzhx944fcday8.png" class="article-body-image-wrapper"&gt;&lt;img 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%2Fupuejtklzhx944fcday8.png" width="800" height="436"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It is given that we need to secure our credentials, especially API Keys that may have been configured to have access to several Google Cloud services and could be a problem, if misused. But what are the recommended best practices to manage and secure your API Keys. This &lt;a href="https://cloud.google.com/blog/topics/developers-practitioners/api-keys-are-open-secrets" rel="noopener noreferrer"&gt;post&lt;/a&gt; goes into the detail while highlighting services like Secret Manager to manage/rotate keys, regular audits and more.&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%2F3nfad5b5fy2hcyvx739w.png" class="article-body-image-wrapper"&gt;&lt;img 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%2F3nfad5b5fy2hcyvx739w.png" width="800" height="323"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Reducing friction for developers trying out developer tools from Google and eventually deploying them on Google, has traditionally faced the common struggle of folks signing up for billing first. With a newly announced deeper integration between Google AI Studio and Google Cloud, you can now vibe code with Google AI Studio with a possible persistent layer backed by Firestore and deploy two applications on Google Cloud Run, without the need of a credit card. Check this &lt;a href="https://cloud.google.com/blog/products/databases/vibe-coded-ai-studio-apps-with-firestore-firebase-cloud-sql" rel="noopener noreferrer"&gt;out&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.amazonaws.com%2Fuploads%2Farticles%2F2wywr1mvap4sjf8wosf8.png" class="article-body-image-wrapper"&gt;&lt;img 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%2F2wywr1mvap4sjf8wosf8.png" width="800" height="418"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Gemini Live Agent Challenge has &lt;a href="https://cloud.google.com/blog/topics/developers-practitioners/winners-and-highlights-of-the-gemini-live-agent-challenge" rel="noopener noreferrer"&gt;announced&lt;/a&gt; the winners and key highlights from the contest that asked developers to integrate real-time multimodal capabilities using the Gemini Live API, the Agent Development Kit (ADK), and Google Cloud infrastructure. The global challenge resulted in projects across three main categories:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Live Agent (Voice)&lt;/li&gt;
&lt;li&gt;Creative Storyteller (Audio / Visual)&lt;/li&gt;
&lt;li&gt;UI Navigator (Gesture-driven interactions)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Notable winners included &lt;a href="https://devpost.com/software/orion-operating-room-intelligent-orchestration-node" rel="noopener noreferrer"&gt;ORION&lt;/a&gt;, a voice-directed surgical co-pilot for robotic surgery; &lt;a href="https://devpost.com/software/drone-copilot" rel="noopener noreferrer"&gt;drone-copilot&lt;/a&gt;, which replaces manual joysticks with natural language voice commands for navigation and autonomous visual inspections; and &lt;a href="https://devpost.com/software/moonwalk-tojsay" rel="noopener noreferrer"&gt;Moonwalk&lt;/a&gt;, a hands-free desktop assistant that automates workflows by controlling the keyboard and mouse through voice.&lt;/p&gt;

&lt;p&gt;AI agent conversations usually go back and forth with a series of questions and usually the interactions end up with just text data and interpreting the intent and extracting data can be not just challenging but more efficient in terms of number of interactions. What if a set of questions that the Agent wants to ask of the user, is converted into a simple UI with the right kind of input controls to select the data from. For e.g. a dropdown, a few checkboxes, etc. Enter A2UI (Agent to UI) Protocol, an open protocol for agent-driven user interfaces and a great example of how this protocol can be embedded into the front-door Gemini Enterprise application is demonstrated in this &lt;a href="https://cloud.google.com/blog/topics/developers-practitioners/guide-to-gemini-enterprise-and-a2ui-integration" rel="noopener noreferrer"&gt;blog post&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.amazonaws.com%2Fuploads%2Farticles%2Fmkuwvt4pazcmuzu3mkyj.png" class="article-body-image-wrapper"&gt;&lt;img 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%2Fmkuwvt4pazcmuzu3mkyj.png" width="800" height="587"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Customers
&lt;/h3&gt;

&lt;p&gt;One of the interesting blog posts that I look forward to each month is one in which we can learn what customers have been building with Google Cloud. For the month of May, there were interesting things that they built. Some of which include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Glance automated its short-form video extraction pipeline by combining Google Cloud Speech-to-Text v2, Gemini 2.5 Flash, the Google Vision API, Samurai object tracking, OpenCV, and MoviePy.&lt;/li&gt;
&lt;li&gt;Urban Outfitters migrated its 11TB Oracle database to AlloyDB for PostgreSQL to power its IBM Sterling OMS, deploying two read replicas to lower data latency for reporting and analytics.&lt;/li&gt;
&lt;li&gt;Movix engineered an agentic AI solution for dental lab quality control using the Gemini Enterprise Agent Platform alongside Cloud Run with L4 GPUs and Compute Engine VMs.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Check out the &lt;a href="https://cloud.google.com/blog/topics/customers/cool-stuff-google-cloud-customers-built-monthly-round-up" rel="noopener noreferrer"&gt;post&lt;/a&gt; for more of what cool things that customers built.&lt;/p&gt;

&lt;h3&gt;
  
  
  Containers and Kubernetes
&lt;/h3&gt;

&lt;p&gt;Google Kubernetes Engine (GKE) Agent Sandbox helps you manage isolated, stateful, and single-replica workloads on GKE. It is optimized for use cases like AI agent runtimes, where untrusted, LLM-generated code must be executed in a secure and performant environment. The GKE Agent Sandbox is now generally available and there is a new introduction too, Agent Substrate. This open source project introduces a minimal control plane that moves agents on and off ready compute capacity in real-time while integrating data locality directly into its scheduler to minimize overhead. . Check out the &lt;a href="https://cloud.google.com/blog/products/containers-kubernetes/bringing-you-agent-sandbox-on-gke-and-agent-substrate" rel="noopener noreferrer"&gt;blog post&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.amazonaws.com%2Fuploads%2Farticles%2Ftltvihwqbh5l4zkxgs0h.png" class="article-body-image-wrapper"&gt;&lt;img 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%2Ftltvihwqbh5l4zkxgs0h.png" width="800" height="542"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Security and Identity
&lt;/h3&gt;

&lt;p&gt;If you are looking to protect your systems from high-speed, automated cybersecurity threats, Google Cloud has introduced Google AI Threat Defense, an autonomous platform built on a four-step framework: Prepare, Scan and Prioritize, Remediate, and Monitor. The system reduces attack surface exposure through Wiz, which maps your live environment and uses an AI penetration testing agent to validate exploitable pathways. When vulnerabilities are discovered, the platform incorporates Mandiant expertise for response planning while CodeMender automatically generates fixes, analyzes library dependencies, and creates verification tests directly inside the developer’s integrated development environment or command-line interface. Check out the &lt;a href="https://cloud.google.com/blog/products/identity-security/introducing-google-ai-threat-defense" rel="noopener noreferrer"&gt;blog post&lt;/a&gt; for more details.&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%2Frd1avllyl8o9oz2phfm6.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frd1avllyl8o9oz2phfm6.gif" width="560" height="276"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The second Cloud CISO Perspectives for May 2026 is &lt;a href="https://cloud.google.com/blog/products/identity-security/cloud-ciso-perspectives-how-to-build-an-ai-ready-security-program-for-the-public-sector" rel="noopener noreferrer"&gt;out&lt;/a&gt;. If you are looking to build an AI-ready security program for the public sector, this article outlines a structured, 12-month roadmap designed to manage complex systems and reduce operational toil. The plan is organized across five core workload domains: executive alignment, process optimization, talent augmentation, posture elevation, and advanced governance.&lt;/p&gt;

&lt;h3&gt;
  
  
  Infrastructure and Networking
&lt;/h3&gt;

&lt;p&gt;There have been several architectural updates to Google’s global and data center networks designed to handle the specific traffic patterns and scale required for AI training and inference workloads. The new Virgo Network serves as a flat, two-layer scale-out data center fabric that connects up to 134,000 eighth-generation TPU chips, delivering increased bandwidth, lower latency, and autonomous reliability features like automated hang and straggler detection to isolate faulty instances. Read more &lt;a href="https://cloud.google.com/blog/products/networking/data-center-and-global-networks-built-for-ai-era" rel="noopener noreferrer"&gt;here&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.amazonaws.com%2Fuploads%2Farticles%2Fjq6y5vv1wl1mdnwdhyrt.png" class="article-body-image-wrapper"&gt;&lt;img 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%2Fjq6y5vv1wl1mdnwdhyrt.png" width="800" height="421"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Given the kind of infrastructure that Google runs, it should be interesting to learn about how they ensure that any optimizations that they introduce to their infrastrcture takes place safely. In fact they run a fleet-wide, machine-level A/B experimentation framework. Instead of testing at the application level, Google enables changes on individual machines across a balanced 1% subset of the fleet to capture system-wide effects for core components like libraries, compilers, kernels, and cluster management systems. Check out the details &lt;a href="https://cloud.google.com/blog/topics/systems/how-google-does-it-fleet-wide-large-scale-ab-experimentation" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  DevOps and SRE
&lt;/h3&gt;

&lt;p&gt;SRE AI is an initiative that integrates agentic AI into Site Reliability Engineering. This includes deploying autonomous AI agents across the entire software development lifecycle. These agents assist in reliability design by creating and updating playbooks, use models like TimesFM for anomaly detection and alert enrichment, and orchestrate incident management by summarizing communications and drafting postmortems. For more details, check out the &lt;a href="https://cloud.google.com/blog/" rel="noopener noreferrer"&gt;blog post&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.amazonaws.com%2Fuploads%2Farticles%2Fxuh884bikinewz36l9fs.png" class="article-body-image-wrapper"&gt;&lt;img 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%2Fxuh884bikinewz36l9fs.png" width="800" height="332"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Application Development
&lt;/h3&gt;

&lt;p&gt;Google Cloud has introduced App-centric maintenance visibility within Unified Maintenance to shift planned maintenance tracking from an infrastructure-focused view to a business-oriented view. By integrating directly with App Hub, Unified Maintenance automatically aggregates the maintenance schedules of registered resources (GKE clusters, GCE VMs, or AlloyDB instances) into a single dashboard centered around the application as the primary unit of management. To use this feature, teams need to enable the Maintenance API and configure application boundaries in the Google Cloud Console. For more details, check out the &lt;a href="https://cloud.google.com/blog/products/application-development/app-centric-maintenance-visibility-in-unified-maintenance" rel="noopener noreferrer"&gt;blog post&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.amazonaws.com%2Fuploads%2Farticles%2F77brhxcyh1ki7ourwf1y.png" class="article-body-image-wrapper"&gt;&lt;img 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%2F77brhxcyh1ki7ourwf1y.png" width="800" height="516"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Continuing on Application Development, we now have a public preview of AppLifecycle Manager Feature Flags (ALM FF). This service decouples feature releases from code deployments, allowing teams to ship code with new features disabled by default and use a toggle as an instant kill switch if issues arise. Built on the open-source OpenFeature standard and the flagd evaluation engine, ALM FF uses Common Expression Language (CEL) to enable targeted rollouts, such as percentage-based traffic ramping or precise allowlisting for specific internal teams and testers. Check out the &lt;a href="https://cloud.google.com/blog/products/application-development/new-feature-flags-in-applifecycle-manager" rel="noopener noreferrer"&gt;blog post&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Learn about Google Cloud
&lt;/h3&gt;

&lt;p&gt;If you have been working with traditional transactional databases and are looking to transition enterprise data from static reports to autonomous systems, Google Cloud outlines a structural evolution across five technical scenarios to manage security, costs, and accuracy. These five scenarios are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Scenario 1: The Static API Contract, which uses pre-written, parameterized SQL queries for deterministic performance.&lt;/li&gt;
&lt;li&gt;Scenario 2: Custom Agent with SQL Generation, where an LLM translates natural language into queries using schema metadata.&lt;/li&gt;
&lt;li&gt;Scenario 3: Conversational Analytics, which uses a platform-native engine grounded in verified query libraries to enforce business logic.&lt;/li&gt;
&lt;li&gt;Scenario 4: Managed MCP Tools introduces the open-source Model Context Protocol (MCP) to decouple the reasoning layer from tool execution via a managed BigQuery server. This helps to scale across different systems.&lt;/li&gt;
&lt;li&gt;Scenario 5: Custom Hosted MCP Servers gives engineers full control to build specialized, multi-source tools on infrastructure like Cloud Run, allowing for programmatic governance and custom data abstraction.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Check out the &lt;a href="https://cloud.google.com/blog/products/data-analytics/building-an-agentic-data-layer-on-google-cloud-5-key-scenarios" rel="noopener noreferrer"&gt;blog post&lt;/a&gt; that provides detailed guidance, queries and more.&lt;/p&gt;

&lt;h3&gt;
  
  
  Write for Google Cloud Medium publication
&lt;/h3&gt;

&lt;p&gt;If you would like to share your Google Cloud expertise with your fellow practitioners, consider becoming an author for Google Cloud Medium publication. Reach out to me via comments and/or fill out this&lt;a href="https://bit.ly/41CGNut" rel="noopener noreferrer"&gt;form&lt;/a&gt; and I’ll be happy to add you as a writer.&lt;/p&gt;

&lt;h3&gt;
  
  
  Stay in Touch
&lt;/h3&gt;

&lt;p&gt;Have questions, comments, or other feedback on this newsletter? Please send &lt;a href="https://forms.gle/UAsAS7YLxYSBTNBy9" rel="noopener noreferrer"&gt;Feedback&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If any of your peers are interested in receiving this newsletter, send them the&lt;a href="https://gcptechnuggets.substack.com/" rel="noopener noreferrer"&gt;Subscribe&lt;/a&gt; link.&lt;/p&gt;




</description>
      <category>googlecloudplatform</category>
      <category>gcpweekly</category>
      <category>gcptechnuggets</category>
    </item>
    <item>
      <title>Antigravity CLI Tutorial Series: Part 2 : Conversations, Conversations and Conversations</title>
      <dc:creator>Romin Irani</dc:creator>
      <pubDate>Sun, 24 May 2026 13:15:36 +0000</pubDate>
      <link>https://dev.to/iromin/antigravity-cli-tutorial-series-part-2-conversations-conversations-and-conversations-j39</link>
      <guid>https://dev.to/iromin/antigravity-cli-tutorial-series-part-2-conversations-conversations-and-conversations-j39</guid>
      <description>&lt;p&gt;Welcome to Antigravity CLI Tutorial.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;The Series:&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/iromin/antigravity-cli-tutorial-series-2mcf"&gt;&lt;em&gt;Part 1 : Getting Started&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Part 2 : Conversations, Conversations, Conversations (this blog)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Codelab&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;: If you prefer to do a hands-on, step-by-step instructional codelab, go directly to the “&lt;/em&gt;&lt;a href="https://codelabs.developers.google.com/antigravity-cli-hands-on#0" rel="noopener noreferrer"&gt;&lt;em&gt;Getting Started with Antigravity CLI Codelab&lt;/em&gt;&lt;/a&gt;&lt;em&gt;”.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In this part of the series, we are going to understanding the mechanics of &lt;strong&gt;Conversations&lt;/strong&gt; in Antigravity CLI.&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%2F1uf0mplenr3kzg00k4tu.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%2F1uf0mplenr3kzg00k4tu.jpeg" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You might already have your own definition of what a conversation means? And you would be right in your approximate definition of it. It is definitely a sequence or a thread of messages exchanged between you (user) and the agent.&lt;/p&gt;

&lt;p&gt;But you would have multiple questions pop up like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Are these conversations stored somewhere?&lt;/li&gt;
&lt;li&gt;How do we manage multiple threads of conversation? Each thread having its own sequence of unique user and agent interactions.&lt;/li&gt;
&lt;li&gt;Can we switch from one conversation to another?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And definitely a lot more questions along similar lines. What follows is my understanding of what &lt;strong&gt;Conversations&lt;/strong&gt; are in Antigravity CLI and an attempt to get the answers to the above questions.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I call these as my experiments since the documentation is sparse at the time of writing and the source code is not open for me to take a peek into. So please correct me if I have hallucinated unintentionally. :-)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  What is a Conversation?
&lt;/h3&gt;

&lt;p&gt;First up, let usattempt to define what a conversation means and what better than to ask Antigravity CLI itself. It came up quite well:&lt;/p&gt;

&lt;p&gt;In the context of Antigravity CLI, &lt;strong&gt;a conversation is an isolated work session or execution thread identified by a unique Conversation ID&lt;/strong&gt; (e.g., &lt;strong&gt;3b4a1d20–3968–4ed2–90b3–00eea3060b02&lt;/strong&gt; ).&lt;/p&gt;

&lt;p&gt;Here is what defines a conversation:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;State and History: Every conversation preserves a history of interactions (user requests, agent responses, tool calls, and system messages) serialized as JSON Lines (JSONL) transcripts under&lt;br&gt;&lt;br&gt;
/brain//.system_generated/logs/ .&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Dedicated Artifacts: Each conversation has its own storage directory&lt;br&gt;&lt;br&gt;
( /brain// ) where structured markdown documents like the implementation_plan.md , task.md , and walkthrough.md are saved and updated.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Scratch Space: Conversations have a dedicated scratchpad directory ( /brain//scratch/ ) for temporary test scripts, helper files, or data files that persist across steps.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Agent Tree: When a main agent invokes a subagent, a new child conversation is spawned with its own ID, allowing agents to work in parallel on specialized sub-tasks while maintaining isolated context.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  What is an appDataDir?
&lt;/h4&gt;

&lt;p&gt;Good question. On my mac, it is in my $HOME/.gemini/antigravity-cli folder or ~/.gemini/antigravity-cli folder. So inside of this directory, you will find the following:&lt;/p&gt;

&lt;p&gt;Inside this directory, you will find the following folder and sub-folders under it (not all subfolders are described):&lt;/p&gt;

&lt;p&gt;brain/ : Contains subdirectories for each conversation (using their Conversation ID) containing:&lt;br&gt;&lt;br&gt;
 — .system_generated/logs/ : Chat transcripts ( transcript.jsonl , transcript_full.jsonl ).&lt;/p&gt;

&lt;p&gt;— Artifacts: Markdown files like implementation_plan.md , task.md , and walkthrough.md .&lt;/p&gt;
&lt;h3&gt;
  
  
  Conversation Management commands
&lt;/h3&gt;

&lt;p&gt;There are several in-built commands in Antigravity CLI that we can use for conversation management. They are:&lt;/p&gt;

&lt;p&gt;• /clear : Clears the screen and starts a fresh conversation thread.&lt;/p&gt;

&lt;p&gt;• /resume (or /switch ): Displays a menu showing your previous conversations, allowing you to choose one to resume.&lt;/p&gt;

&lt;p&gt;• /rewind (or /undo ): Rolls back the active conversation history to a previous step (useful if a command failed or you want to try a different direction).&lt;/p&gt;

&lt;p&gt;• /fork : Branches the current conversation into a new workspace from a specific step, preserving history up to that point.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;/rename  : Renames the active conversation with a custom, readable title.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Let’s see it work
&lt;/h3&gt;

&lt;p&gt;Let’s ensure that we are starting a fresh conversation thread. To do that, you can use /clear command. This can be used anytime to create a new conversation. This does not lose any of the previous conversation and we can always switch back to previous conversation threads. We will see all of that in a while.&lt;/p&gt;

&lt;p&gt;But for now, just ensure that you have used the /clear command and are ready in Antigravity CLI.&lt;/p&gt;

&lt;p&gt;Give the following prompt:&lt;/p&gt;

&lt;p&gt;What is Google Cloud Run?&lt;/p&gt;

&lt;p&gt;Antigravity CLI gets down to work and produces the following output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;● WebSearch(Google Cloud Run overview features) (ctrl+o to expand)

  Google Cloud Run is a fully managed, serverless platform by Google Cloud that allows you to run containerized applications and services without having to manage the underlying server infrastructure. It combines the flexibility of        
  containers with the simplicity of serverless computing.                                                                                                                                                                                      

  ### Key Features                                                                                                                                                                                                                             

  • Fully Managed &amp;amp; Serverless: Google automatically handles infrastructure management, including server provisioning, operating system maintenance, and scaling.                                                                              
  • Automatic Scaling: Cloud Run scales automatically based on incoming request traffic. It can scale up to thousands of instances to handle high demand, and scale down to zero when there is no traffic, meaning you only pay when your      
  application is actively handling requests.                                                                                                                                                                                                   
  • Any Language or Library: Since it runs Docker/OCI-compliant containers, you can write your application in any programming language (e.g., Python, Node.js, Go, Java, Rust) and use any system library or custom dependency.                
  • Deploy from Source or Container: You can deploy an existing container image from Google Artifact Registry or deploy directly from your source code repository. If deploying from source, Cloud Run uses Google Cloud Buildpacks to         
  automatically package your code into a container.                                                                                                                                                                                            
  • Two Execution Modes:                                                                                                                                                                                                                       
      • Cloud Run Services: For web apps, APIs, microservices, or event-driven applications that respond to incoming web/HTTP requests or gRPC calls.                                                                                          
      • Cloud Run Jobs: For short-lived, run-to-completion tasks (like database migrations, nightly backups, or batch data processing) that do not serve web traffic.                                                                          
  • Hardware and AI Acceleration: It supports deploying workloads on GPUs (such as NVIDIA L4) and using larger machine configurations, making it a viable serverless platform for hosting Large Language Models (LLMs) and running AI inference
  workloads.                                                                                                                                                                                                                                   
  • Integrations: It integrates natively with other Google Cloud services (such as Pub/Sub, Cloud Storage, and Eventarc for event-driven workflows) and supports VPC connectivity to securely access private databases or other internal       
  resources.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But what has it done behind the scenes to persist this conversation thread.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
The Antigravity CLI instantly performs the following directory setup (I am assuming the following conversation id → 11111111–2222–3333–4444–555555555555):&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Creates the Conversation Root Folder:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;~/.gemini/antigravity-cli/brain/11111111–2222–3333–4444–555555555555/&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Creates the System Logs Folder:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;~/.gemini/antigravity-cli/brain/11111111–2222–3333–4444–555555555555/.system_generated/logs/&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Creates the Scratchpad Directory:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;~/.gemini/antigravity-cli/brain/11111111–2222–3333–4444–555555555555/scratch/ (This folder remains empty until the agent needs to write temporary test scripts or run one-off diagnostics).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2: Logging the Initial Prompt (Internal System Logs)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The CLI creates two JSON Lines files under the .system_generated/logs/ folder:&lt;/p&gt;

&lt;p&gt;• transcript.jsonl (assuming that this is a token-efficient log containing truncated text for large outputs)&lt;/p&gt;

&lt;p&gt;• transcript_full.jsonl (assuming that this is a full, untruncated log containing exact tool results and text)&lt;/p&gt;

&lt;p&gt;If you visit the transcript.jsonl file, you will notice that a JSON record representing your first input step is appended (few fields only since there is a lot of metadata too):&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;"step_index"&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="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"source"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"USER_EXPLICIT"&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="s2"&gt;"USER_INPUT"&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="s2"&gt;"DONE"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"content"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"What is Google Cloud Run?"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You will also see multiple steps being recorded next in terms of how Antigravity CLI is planning out its execution. I will only reproduce the steps / types, etc and it will be good enough for you to understand. I encourage you to inspect the files on your machine to see all the wonderful details.&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="nl"&gt;"step_index"&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="nl"&gt;"source"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"SYSTEM"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"CONVERSATION_HISTORY"&lt;/span&gt;&lt;span class="err"&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="nl"&gt;"step_index"&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="nl"&gt;"source"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"MODEL"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"PLANNER_RESPONSE"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"DONE"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"created_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"2026-05-24T12:14:37Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"tool_calls"&lt;/span&gt;&lt;span class="p"&gt;:[{&lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"search_web"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;&lt;span class="nl"&gt;"query"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;Google Cloud Run overview features&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"toolAction"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;Searching the web&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"toolSummary"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;Web search&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&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="nl"&gt;"step_index"&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="nl"&gt;"source"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"MODEL"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"SEARCH_WEB"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"DONE"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"created_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"2026-05-24T12:14:38Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"content"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"Created At: 2026-05-24T12:14:38Z&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;Completed At: 2026-05-24T12:14:43Z&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;The search for &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;Google Cloud Run overview features&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt; returned the following summary:&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;Google Cloud Run is a fully managed, serverless platform that allows you to run containerized applications and services without managing the underlying infrastructure[1][2][3]. It is designed to combine the flexibility of containers with the simplicity of a serverless environment[4].&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s2"&gt;### Core Features&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s2"&gt;* **Fully Managed &amp;amp; Serverless:** Google handles all infrastructure management, including provisioning, scaling, and maintenance[1][2]. You simply provide your code or container[3][4].&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;* **Automatic Scaling:** Cloud Run s.....}
...
{"&lt;/span&gt;&lt;span class="err"&gt;step_index&lt;/span&gt;&lt;span class="s2"&gt;":5,"&lt;/span&gt;&lt;span class="err"&gt;source&lt;/span&gt;&lt;span class="s2"&gt;":"&lt;/span&gt;&lt;span class="err"&gt;MODEL&lt;/span&gt;&lt;span class="s2"&gt;","&lt;/span&gt;&lt;span class="err"&gt;type&lt;/span&gt;&lt;span class="s2"&gt;":"&lt;/span&gt;&lt;span class="err"&gt;PLANNER_RESPONSE&lt;/span&gt;&lt;span class="s2"&gt;","&lt;/span&gt;&lt;span class="err"&gt;status&lt;/span&gt;&lt;span class="s2"&gt;":"&lt;/span&gt;&lt;span class="err"&gt;DONE&lt;/span&gt;&lt;span class="s2"&gt;","&lt;/span&gt;&lt;span class="err"&gt;created_at&lt;/span&gt;&lt;span class="s2"&gt;":"&lt;/span&gt;&lt;span class="mi"&gt;2026-05-24&lt;/span&gt;&lt;span class="err"&gt;T&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;46&lt;/span&gt;&lt;span class="err"&gt;Z&lt;/span&gt;&lt;span class="s2"&gt;","&lt;/span&gt;&lt;span class="err"&gt;content&lt;/span&gt;&lt;span class="s2"&gt;":"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;**Google&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Cloud&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Run**&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;is&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;fully&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;managed&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;serverless&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;platform&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;by&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Google&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Cloud&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this way, your current conversation as you go back and forth is persisted.&lt;/p&gt;

&lt;p&gt;See what happens if you give a follow up message that says:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;What kind of applications can I deploy on Google Cloud Run?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once you get the response in Antigravity CLI terminal, go back to the conversation id folder and you will see additional steps in the transcript.jsonl file:&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="nl"&gt;"step_index"&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="nl"&gt;"source"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"USER_EXPLICIT"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"USER_INPUT"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"DONE"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"created_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"2026-05-24T12:27:18Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"content"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;USER_REQUEST&amp;gt;&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;What kind of applications can I deploy on Google Cloud Run?&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/USER_REQUEST&amp;gt;&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;ADDITIONAL_METADATA&amp;gt;&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;The current local time is: 2026-05-24T17:57:18+05:30.&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/ADDITIONAL_METADATA&amp;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="nl"&gt;"step_index"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"source"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"MODEL"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"PLANNER_RESPONSE"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"DONE"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"created_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"2026-05-24T12:27:18Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"content"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"You can deploy a wide variety of applications on...}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 3: Agent Analysis and Planning (If coding changes are needed)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now, let’s say we go a step further and ask it to actually generate/code a sample application for us that can be deployed on Cloud Run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Create a single page HTML / JavaScript application to deploy on Cloud Run that takes my name and returns me a greeting.
Let's plan it out first.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here I am specifically asking it to plan it out first. It comes back saying:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; I have created the implementation plan for the Google Cloud Run greeting application.                                                                                                                                                        

  Please review the proposed design and files in the implementation_plan.md artifact. Once you approve, let me know and we will proceed to verify it.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This behind the scenes creates:&lt;br&gt;&lt;br&gt;
~/.gemini/antigravity-cli/brain/11111111–2222–3333–4444–555555555555/implementation_plan.md&lt;/p&gt;

&lt;p&gt;Depending on how you proceed, additional markdown files (walkthrough, task list, etc) will be created in the same folder.&lt;/p&gt;

&lt;p&gt;As an experiment, go ahead with approving the implementation plan. This will make Antigravity CLI generate the code, test out the server, etc. This will result in additional folders being created but all within the brain/CONVERSATION_ID folder.&lt;/p&gt;

&lt;p&gt;If you navigate to your app data folder during/after a coding conversation, here is exactly what you would start seeing something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;~/.gemini/antigravity-cli/
└── brain/
└── 11111111–2222–3333–4444–555555555555/ ← Root of the conversation
├── .system_generated/
│ └── logs/
│ ├── transcript.jsonl ← Truncated log
│ └── transcript_full.jsonl ← Untruncated full log
├── implementation_plan.md ← Technical design spec
├── task.md ← Interactive checklist
└── walkthrough.md ← Work summary &amp;amp; verification
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A few other things worth mentioning are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You will find a history.jsonl within the ~/.gemini/antigravity-cli folder that seems to be a index of all conversations.&lt;/li&gt;
&lt;li&gt;A conversations folder that holds the conversations in a protocol buffer format. We can leave it as is for now.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Let’s Rewind
&lt;/h3&gt;

&lt;p&gt;What if we want to go back at a point in time in the conversation. Remember we started with asking about Google Cloud Run, then we asked it to generate code for the application and so on. As a result of which, several code files, artifacts etc have been generated.&lt;/p&gt;

&lt;p&gt;If I go into shell mode and see the current files in the folder, you can see from the output below, the files that are currently present. So far so good.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;● ! ls
  ⎿ Dockerfile
     node_modules
     package-lock.json
     package.json
     public
     README.md
     server.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, give the /rewind command and you should see a list of all interactions that you have had. In my case, you see the current conversation thread with the list of interactions. I can use the keyboard to go up at the specific point in time before the files were generated (8 files changed, etc).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Rewind Conversation

  What is Google Cloud Run?

&amp;gt; What kind of applications can I deploy on Google Cloud Run?

  Create a single page HTML / JavaScript application to deploy on Cloud Run tha...
    8 files changed +583 -1

  Could you first plan it out?
    1 artifact generated

  what is the history.jsonl file that you are managing for the conversations

  what is a .pb file and how are you using it for conversations

  (current)

Keyboard: ↑/↓ Navigate enter Select esc Cancel
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once I select to rewind it to a step before all the files were generated and execute that step, it will remove the files generated as is evident from the outputs that I now see.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;● ! ls
  ⎿ node_modules
     package-lock.json
     public
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The implementation_plan.md and other artifact files also go away from the brain/CONVERSATION_ID folder that we earlier saw. You can try out these scenarios on your machine.&lt;/p&gt;

&lt;h3&gt;
  
  
  Saving a Conversation with a different name
&lt;/h3&gt;

&lt;p&gt;At any point in time, you can save the conversation with a name that is easier or makes sense to you in terms of the entire thread. Just use the /rename command.&lt;/p&gt;

&lt;p&gt;In Antigravity CLI, I simply give the rename Google Cloud Run basics to rename this conversation. It comes back with the following message:&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; /rename
  ⎿ Conversation renamed to: Google Cloud Run basics
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Switching between Conversations
&lt;/h3&gt;

&lt;p&gt;You can use the /resume or /switch command to switch to another conversation. For example, I see the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   CLI Antigravity (tab to cycle)

  Conversations
  Type to search...
&amp;gt; [CURRENT] Google Cloud Run basics 10 steps 8m ago
  Understanding Antigravity CLI Conversations 24 steps 52m ago
  hello 4 steps 1h ago

Keyboard: ↑/↓ Navigate ←/→ Page enter Select f2 Rename ctrl+delete Delete tab Switch Tab esc Go back / Clear search
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can see that our current context is now with our preferred name Google Cloud Run basics and the other ones that you see in the list are the ones that I had here. But you might see another list.&lt;/p&gt;

&lt;p&gt;Select any one of these to switch to that conversation and carry on that conversation from there or maybe even rewind, etc.&lt;/p&gt;

&lt;h3&gt;
  
  
  Switching to an Antigravity conversation
&lt;/h3&gt;

&lt;p&gt;If you have been paying attention to the output shown in the /switch command, you might see an Antigravity and CLI option. This might happen only if you have also installed the non-CLI option i.e. Antigravity on your machine. In my case I have and have interacted a bit with it.&lt;/p&gt;

&lt;p&gt;But what is pleasantly surprising is that it is now showing me conversations that have been saved via Antigravity and allowing me to import them. Whew! Let’s try this out:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   CLI Antigravity (tab to cycle)

  Conversations
  Type to search...
&amp;gt; Extracting Invoice Information [Import this conversation? (y/n)] 20 steps 2h ago
  Generate a events website but let's discuss the requirements first. 67 steps 1d ago

Keyboard: ↑/↓ Navigate enter Select tab Switch Tab esc Go back / Clear search
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So I select one of the conversations (Extracting Invoice Information) and then press on Enter. It asks me that it needs to import this conversation. This brought up the previous conversation and I was able to carry on with a new message in the thread. Wonderful. Probably this needs a lot more testing.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  &amp;lt;PREVIOUS _ CONVERSATION _ THREAD &amp;gt;

────────────────────────────────────────────────────────────
&amp;gt; What are the files sizes for each of the invoices

● ListDir(/Users/romin/agy-cli-projects/invoice-processing) (ctrl+o to expand)

  Here are the file sizes for each of the invoice image files in your directory:                                                                                                                                                               

  • inv1.png: 273,828 bytes (approx. 273.8 KB)                                                                                                                                                                                           
  • inv2.png: 369,086 bytes (approx. 369.1 KB)                                                                                                                                                                                           
  • inv3.png: 446,932 bytes (approx. 446.9 KB)                                                                                                                                                                                           
  • inv4.png: 343,328 bytes (approx. 343.3 KB)                                                                                                                                                                                           

  (Note: The CHUBB.pdf insurance document size is 42,965 bytes / approx. 43 KB).   
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  One more thing
&lt;/h3&gt;

&lt;p&gt;If you quit your Antigravity CLI at this point, you will notice that there is a message at the end that looks something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Resume: agy &lt;span class="nt"&gt;--conversation&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;d1d8a55b-cc27-4dd4-bc62-2f73015960d2 &lt;span class="o"&gt;(&lt;/span&gt;or &lt;span class="nt"&gt;-c&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That’s right. Antigravity CLI comes with a command line option to resume a specific conversation via the --conversation or -c parameter. This value has to be the unique conversation id that you see. I think this is useful but might be a bit unwieldy to remember or use.&lt;/p&gt;

&lt;p&gt;In any case, the key message is that you now what is going on with this unique conversation id , where the stuff is persisted on your local machine and can discover more. In any case, you can always launch Antigravity CLI and use the /switch command to go to a specific conversation thread. Just remember to use /rename to name them in a way that you understand.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;While a conversation in Antigravity CLI is something that is managed behind the scenes for you, it is helpful to understand how the tool is working. Hopefully these examples give you a good idea of what is happening under the hood. I will keep adding more examples to this as I understand this better. See you in latter parts of the series.&lt;/p&gt;




</description>
      <category>antigravitycli</category>
      <category>gettingstarted</category>
      <category>tutorial</category>
      <category>conversations</category>
    </item>
    <item>
      <title>Antigravity CLI Tutorial Series</title>
      <dc:creator>Romin Irani</dc:creator>
      <pubDate>Fri, 22 May 2026 15:08:49 +0000</pubDate>
      <link>https://dev.to/iromin/antigravity-cli-tutorial-series-2mcf</link>
      <guid>https://dev.to/iromin/antigravity-cli-tutorial-series-2mcf</guid>
      <description>&lt;h3&gt;
  
  
  Getting Started with Antigravity CLI : Tutorial Series
&lt;/h3&gt;

&lt;p&gt;Welcome to the Antigravity CLI Tutorial Series. Antigravity CLI is the terminal-first interface to work with Antigravity Agents. It can be used for all kinds of tasks ranging from coding to automating repeated tasks.&lt;/p&gt;

&lt;p&gt;Welcome to Antigravity CLI Tutorial.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;The Series:&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Part 1 : Getting Started(this blog)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/iromin/antigravity-cli-tutorial-series-part-2-conversations-conversations-and-conversations-j39"&gt;Part 2 : Conversations, Conversations, Conversations&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Codelab&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;: If you prefer to do a hands-on, step-by-step instructional codelab, go directly to the “&lt;/em&gt;&lt;a href="https://codelabs.developers.google.com/antigravity-cli-hands-on#0" rel="noopener noreferrer"&gt;&lt;em&gt;Getting Started with Antigravity CLI Codelab&lt;/em&gt;&lt;/a&gt;&lt;em&gt;”.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://antigravity.google/docs/cli-overview" rel="noopener noreferrer"&gt;Antigravity CLI&lt;/a&gt; is part of the Antigravity 2 release. As the documentation states, “It brings the same core agentic capabilities as Antigravity 2.0 — including multi-step reasoning, multi-file editing, tool calling, and conversation history — directly to your terminal.”&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%2Fts26upkot8ps9rviffib.png" class="article-body-image-wrapper"&gt;&lt;img 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%2Fts26upkot8ps9rviffib.png" width="800" height="450"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Reference: &lt;a href="https://antigravity.google/product/antigravity-cli" rel="noopener noreferrer"&gt;https://antigravity.google/product/antigravity-cli&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Here are a few highlights at the time of the initial announcement, in terms of what Antigravity CLI brings to the table:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Faster Execution:&lt;/strong&gt; The new CLI is built in Go, making it noticeably snappier and more responsive than its predecessor.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Asynchronous Workflows:&lt;/strong&gt; This is a huge productivity boost. Users can now run large-scale tasks (like codebase refactors or deep research) in the background. The CLI will orchestrate the agents without locking up the active terminal session.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unified Architecture:&lt;/strong&gt; The CLI shares the same backend agent harness as the new desktop app, &lt;a href="https://antigravity.google/blog/introducing-google-antigravity-2-0" rel="noopener noreferrer"&gt;Antigravity 2.0&lt;/a&gt;. This means any future improvements to the core agents will instantly apply to the terminal experience.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;If you are looking for &lt;a href="https://geminicli.com/" rel="noopener noreferrer"&gt;Gemini CLI&lt;/a&gt;, this is not the same as Antigravity CLI. Gemini CLI is the open-source version terminal interface that lets you use the power of the Gemini model for your tasks via natural language. It has its own ecosystem of &lt;a href="https://geminicli.com/extensions/" rel="noopener noreferrer"&gt;Extensions&lt;/a&gt; and I have written a &lt;a href="https://medium.com/google-cloud/gemini-cli-tutorial-series-77da7d494718" rel="noopener noreferrer"&gt;tutorial series&lt;/a&gt; on that earlier.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Blog Updates&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;04-Jun-2026 : Added section on understanding what changes have happened to Antigravity CLI via the agy changelog command. Added a new section on models subcommand introduced in 1.0.5 to get the current list of models supported and how to pass the model to the Antigravity CLI via the --model command-line parameter.&lt;br&gt;&lt;br&gt;
24-May-2026 : Added section on AGY CLI command-line parameters. Updated installation section with agy update command.&lt;br&gt;&lt;br&gt;
23-May-2026 : Updated the installation instructions. Added new sections on /btw command and /context command to visualize context.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;
  
  
  Installation
&lt;/h3&gt;

&lt;p&gt;The installation is straightforward and binaries are available across major Operating System. I have taken the commands to run in the terminal directly from the installation document:&lt;/p&gt;
&lt;h4&gt;
  
  
  macOS | Linux
&lt;/h4&gt;

&lt;p&gt;curl -fsSL &lt;a href="https://antigravity.google/cli/install.sh" rel="noopener noreferrer"&gt;https://antigravity.google/cli/install.sh&lt;/a&gt; | bash&lt;/p&gt;
&lt;h4&gt;
  
  
  Windows PowerShell
&lt;/h4&gt;

&lt;p&gt;irm &lt;a href="https://antigravity.google/cli/install.ps1" rel="noopener noreferrer"&gt;https://antigravity.google/cli/install.ps1&lt;/a&gt; | iex&lt;/p&gt;
&lt;h4&gt;
  
  
  Windows CMD
&lt;/h4&gt;

&lt;p&gt;curl -fsSL &lt;a href="https://antigravity.google/cli/install.cmd" rel="noopener noreferrer"&gt;https://antigravity.google/cli/install.cmd&lt;/a&gt; -o install.cmd &amp;amp;&amp;amp; install.cmd &amp;amp;&amp;amp; del install.cmd&lt;/p&gt;

&lt;p&gt;This should ideally setup and install the Antigravity CLI (agy) in your system and in the Path.&lt;/p&gt;

&lt;p&gt;For e.g. on my MacOS , the installer copied and setup the following executable here: /Users/romin/.local/bin/agyand there was an entry made in the profile to add that folder to the path.&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;# Added by Antigravity CLI installer&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"/Users/romin/.local/bin:&lt;/span&gt;&lt;span class="nv"&gt;$PATH&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In some cases, if the installer is not able to add the binary ( agy to the PATH), it will say so. For e.g. on another machine, I saw the following output, where it will clearly tell you what to do, to add it to the PATH.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;% curl -fsSL https://antigravity.google/cli/install.sh | bash
⠋ Detecting system environment...
✓ Platform detected: darwin_arm64
⠋ Querying release repository...
✓ Latest available version: 1.0.1
⠋ Downloading release package...
✓ Download complete and checksum verified.
⠋ Extracting binary from archive...
⠋ Configuring shell environment...
I0523 11:44:14.012088 76528 installer.go:27] Running Antigravity CLI setup...
Warning: /Users/neilirani/.local/bin is not present in your active PATH.
To use the 'agy' CLI globally, please manually add it to your shell profile:
  echo 'export PATH="/Users/neilirani/.local/bin:$PATH"' &amp;gt;&amp;gt; ~/.zshrc &amp;amp;&amp;amp; source ~/.zshrc
✅ Antigravity CLI binary placed successfully at /Users/neilirani/.local/bin/agy
Note: The binary is installed, but it is not in your active PATH. Please follow the instructions above to add it, then restart your terminal session.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I suggest that we start with a specific folder agy-cli-projects and work through that for the rest of the tutorial.&lt;/p&gt;

&lt;p&gt;Create a folder named agy-cli-projects and navigate into that. I have created it in my home folder but you can do that based on your preference.&lt;/p&gt;

&lt;p&gt;Just check out the version of Antigravity CLI via the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;agy &lt;span class="nt"&gt;--version&lt;/span&gt;
&lt;span class="go"&gt;1.0.2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Updating Antigravity CLI
&lt;/h4&gt;

&lt;p&gt;You can update Antigravity CLI at any time via the agy update command. This checks for newer versions and then downloads and updates your current local installation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Changelog&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
It is a good idea to check the changelog to get a sense of the updates that have happened across different versions of Antigravity CLI. Use the agy changelog command for that. A sample (partial) run for the latest update at the time of writing is shown below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;$ agy changelog
&lt;span class="p"&gt;1.&lt;/span&gt;0.5:
· Added &lt;span class="sb"&gt;`--model`&lt;/span&gt; to set model when launching CLI. Also a new &lt;span class="sb"&gt;`models`&lt;/span&gt; subcommand to list available models.
· Added &lt;span class="sb"&gt;`/permissions`&lt;/span&gt; command which allows to add/edit/remove permissions rules for each of the three configs above directly inside the CLI.
· Allowed opening the Artifact Review panel (shortcut &lt;span class="sb"&gt;`ctrl+r`&lt;/span&gt;) while answering pending questions or tool permission confirmations, preserving your current progress when toggling back.
· Fixed a bug that metadata was written in the current directory as opposed to &lt;span class="sb"&gt;`~/.gemini/antigravity-cli/cache`&lt;/span&gt; when running using &lt;span class="sb"&gt;`-p`&lt;/span&gt;.
· Improved statusline layout by merging active tip and artifact status on a single line and truncating with ellipsis on narrow terminals to prevent collisions.
· Improved customization support by allowing directories in the customization manager to be passed as workspace directories, enabling correct trajectory metadata population and &lt;span class="sb"&gt;`/add-dir`&lt;/span&gt; support.
· Added support for &lt;span class="sb"&gt;`url`&lt;/span&gt; in &lt;span class="sb"&gt;`mcp_config.json`&lt;/span&gt; to configure MCP servers directly via a URL.
· Improved &lt;span class="sb"&gt;`/resume`&lt;/span&gt; performance: optimized lazy loading of conversation details, filtered out empty conversations, and added support for scanning SQLite database files (&lt;span class="sb"&gt;`.db`&lt;/span&gt; and &lt;span class="sb"&gt;`.db-wal`&lt;/span&gt;).
· Improved autocomplete: tab completion for slash commands now resolves to the matched alias instead of the primary command name (e.g., &lt;span class="sb"&gt;`/se`&lt;/span&gt; autocompletes to &lt;span class="sb"&gt;`/settings`&lt;/span&gt; instead of &lt;span class="sb"&gt;`/config`&lt;/span&gt;).
· Integrated the permissioning system with the rest of Antigravity. CLI permissions now merges project level permissions, permissions from user settings shared with Antigravity, and permissions from the CLI &lt;span class="sb"&gt;`settings.json`&lt;/span&gt;.
&lt;span class="p"&gt;
1.&lt;/span&gt;0.4:
· Added SQLite (.db) conversation support and will be CLI’s conversation format. Fixed a bug when importing SQLite conversation from Antigravity 2.0 to CLI.
· Added LaTeX math rendering, enabling the CLI to display beautiful mathematical formulas directly in the terminal viewport. Set &lt;span class="sb"&gt;`AGY_CLI_DISABLE_LATEX`&lt;/span&gt; environment variable to turn off LaTeX rendering globally if desired.
· Decoupled project discovery from local &lt;span class="sb"&gt;`.antigravitycli`&lt;/span&gt; workspace directories. The CLI now stores workspace-to-project mappings in a centralized &lt;span class="sb"&gt;`~/.gemini/antigravity-cli/cache/projects.json`&lt;/span&gt; file, eliminating repository clutter and speeding up project discovery to a single-map lookup.
· Resolved sporadic and permanent UI hangs caused by a stateful callback streamer race condition during network drops or extremely fast agent steps.
· Collapses all newlines and consecutive whitespaces in conversation previews and titles before rendering list items, preventing visual UI layout breaks in the picker rows.
· Styled the separator space between the line number column and diff content to match the text blocks, ensuring background highlights stretch seamlessly across the viewport width in tool outputs and &lt;span class="sb"&gt;`/diff`&lt;/span&gt; details.
· Resolved inconsistent behavior where selecting skill-derived slash commands from autocompletion suggestions cleared the input without executing. Autocompleted skill commands are now correctly submitted to the backend.
...
&lt;span class="p"&gt;
1.&lt;/span&gt;0.3: ...
&lt;span class="p"&gt;
1.&lt;/span&gt;0.2: ...

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Logging into Antigravity CLI
&lt;/h3&gt;

&lt;p&gt;When we launch Antigravity CLI for the first time, it will ask you to login. Launch agy and it should show something similar to this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
     ▄▀▀▄
    ▀▀▀▀▀▀
   ▀▀▀▀▀▀▀▀
  ▄▀▀ ▀▀▄
 ▄▀▀ ▀▀▄

 Welcome to the Antigravity CLI. You are currently not signed in.

 Select login method:
 &amp;gt; 1. Google OAuth
   2. Use a Google Cloud project

 [Use arrow keys to navigate, Enter to select]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use your personal account for now. Choose 1. Google OAuth and press Enter. This will launch a browser and you can login with your Google Account. On successful authentication and authorization, you are asked to copy a code. Please come back into the Antigravity CLI terminal and paste the code.&lt;/p&gt;

&lt;p&gt;Once the login is successful, a few things happen:&lt;/p&gt;

&lt;p&gt;First up, it asks you about the color theme that you wish to choose for Antigravity CLI, as shown below. Pick the one that you like.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvo63jplvcgvngpjlvo1s.png" class="article-body-image-wrapper"&gt;&lt;img 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%2Fvo63jplvcgvngpjlvo1s.png" width="800" height="444"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next up, you need to accept a few terms of service:&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%2Fv7qcvs44752pmgwx2zht.png" class="article-body-image-wrapper"&gt;&lt;img 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%2Fv7qcvs44752pmgwx2zht.png" width="800" height="435"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Finally, the most important thing is to give your permission that you trust the folder, as shown below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Accessing workspace:

/Users/romin/agy-cli-projects

Do you trust the contents of this project?

Antigravity CLI requires permission to read, edit, and execute files here.

&amp;gt; Yes, I trust this folder
  No, exit

  ↑/↓ Navigate · enter Confirm
                                                                                                                                   Gemini 3.5 Flash (High)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You will see this typically in any new folder that you launch the Antigravity CLI on. We will come to more on this later in the series but for now, go ahead and say Yes, I trust this folder.&lt;/p&gt;

&lt;p&gt;You are all set now and its waiting for your prompt:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
      ▄▀▀▄ Antigravity CLI 1.0.1
     ▀▀▀▀▀▀ &amp;lt;YOUR_ACCOUNT_EMAIL&amp;gt;
    ▀▀▀▀▀▀▀▀ Gemini 3.5 Flash (High)
   ▄▀▀ ▀▀▄ ~/agy-cli-projects
  ▄▀▀ ▀▀▄

───────────────────────────────────────────────────────────
&amp;gt;
───────────────────────────────────────────────────────────
? for shortcuts Gemini 3.5 Flash (Medium)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Antigravity CLI — A few housekeeping commands
&lt;/h3&gt;

&lt;p&gt;Notice that it is using Gemini 3.5 Flash as shown in the bottom right. The first thing ideally is to understand that most of the customization and settings that you need to do are available via the /config or /settingscommand.&lt;/p&gt;

&lt;h4&gt;
  
  
  Configuration / Settings
&lt;/h4&gt;

&lt;p&gt;Go ahead and invoke the /config command. This will bring up various areas of Antigravity that you can customize based on your preferences. This includes the Color Scheme, Tool permission, telemetry settings and more.&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%2Ft6snsvpg1nqzcf222k2i.png" class="article-body-image-wrapper"&gt;&lt;img 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%2Ft6snsvpg1nqzcf222k2i.png" width="800" height="677"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For example, the Color Scheme brings up the following options, from which I can choose my preferred color scheme:&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%2Frnb0bbkreowmrmah0mba.png" class="article-body-image-wrapper"&gt;&lt;img 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%2Frnb0bbkreowmrmah0mba.png" width="800" height="302"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  settings.json
&lt;/h4&gt;

&lt;p&gt;The configuration settings need to be stored somewhere right? All of them get stored in ~/.gemini/antigravity-cli/settings.json file. A sample is shown below:&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;"colorScheme"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"dark"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="nl"&gt;"model"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Gemini 3.5 Flash (High)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="nl"&gt;"statusLine"&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;""&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;""&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="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;"trustedWorkspaces"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
         &lt;/span&gt;&lt;span class="s2"&gt;"/Users/romin/antigravity-cli-projects"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
         &lt;/span&gt;&lt;span class="s2"&gt;"/Users/romin/agy-cli-projects"&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can notice the colorScheme that I have selected, the model and also various folders from where I have started Antigravity CLI and said yes to trusting the folders.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; You can modify the settings.json directly too and restart Antigravity CLI as a best practice to see the changes. But be sure of the settings, else it will display an error at startup. I suggest that given that the documentation is sparse at the moment, use the /settings or /config command in the Antigravity CLI to work with this file.&lt;/p&gt;

&lt;h4&gt;
  
  
  Tool Permission
&lt;/h4&gt;

&lt;p&gt;An important setting to understand is the Tool Permission and I show the options below. You can get to this via the /config command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Tool Permission
  &amp;gt; request-review (current)
    proceed-in-sandbox
    always-proceed
    strict
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By default, it is set to request-review. Let’s understand this in more detail:&lt;/p&gt;

&lt;p&gt;In Antigravity, Tool Permission settings control the balance between security (guarding your host system against unintended changes) and velocity (how autonomously the agent can work without pausing for your input).&lt;/p&gt;

&lt;p&gt;request-review (Current Default)&lt;br&gt;&lt;br&gt;
In this mode, the agent is treated as a collaborative partner that checks in before performing any action that could affect your system or project files outside of pre-approved bounds.&lt;/p&gt;

&lt;p&gt;How it works: Whenever the agent attempts to run a terminal command, perform a file operation (like writing/deleting), or call an external service where permission hasn’t been pre-approved, the execution pauses. The user is prompted to approve or reject the specific action.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The agent needs to install a package using npm install lodash.Instead of running the command immediately, the CLI pauses and shows a prompt as shown below, and you have choice to decide whether to allow it to proceed or so on. &lt;strong&gt;It is recommended that you can keep this default setting, so that you get familiar with how your commands are being run.&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Requesting permission for: npm install lodash

Do you want to proceed?
&amp;gt; 1. Yes
  2. Yes, and always allow in this conversation for commands that start with 'npm install'
  3. Yes, and always allow for commands that start with 'npm install' (Persist to settings.json)
  4. No
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;proceed-in-sandbox&lt;/p&gt;

&lt;p&gt;This mode allows the agent to execute terminal commands automatically, but within a secure, isolated container. The agent can run commands without prompting you, but those commands are executed in a virtualized sandbox (e.g., a lightweight container). They cannot modify your actual host machine’s filesystem or access your local network.&lt;/p&gt;

&lt;p&gt;always-proceed&lt;/p&gt;

&lt;p&gt;This is the fully autonomous mode, giving the agent maximum speed and capability. The agent is granted full permission to run commands and write files directly on your host machine. It will never prompt you for confirmation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
You leave a long-running task running overnight using the /goal command (e.g., “Refactor our styling system to use vanilla CSS and ensure all components build without error”). In this scenario, The agent writes dozens of files, runs npm run build , resolves compiler errors, installs helper packages, and runs git commands entirely on its own. The work completes without ever pausing to wait for your approval. &lt;strong&gt;(Use with caution: only use this in trusted, version-controlled repositories)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;strict&lt;/p&gt;

&lt;p&gt;This is a zero-trust, high-security mode. The agent’s capabilities are restricted to executing &lt;strong&gt;read&lt;/strong&gt; tools. All &lt;strong&gt;non-read&lt;/strong&gt; tools will require the user to be prompted for action.&lt;/p&gt;
&lt;h4&gt;
  
  
  Set a model
&lt;/h4&gt;

&lt;p&gt;You can use the /model command to select a model that will be used. At the time of writing, this is the list of models shown when you use the /model command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Switch Model

&amp;gt; Gemini 3.5 Flash (High) (current)
  Gemini 3.5 Flash (Medium)
  Gemini 3.1 Pro (High)
  Gemini 3.1 Pro (Low)
  Claude Sonnet 4.6 (Thinking)
  Claude Opus 4.6 (Thinking)
  GPT-OSS 120B (Medium)

Keyboard: ↑/↓ Navigate enter Select esc Go Back
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can choose any of the models as needed, based on your preference.&lt;/p&gt;

&lt;p&gt;You do have an option of setting the model while starting a agy session. You can do that via the agy --model "model_name" command line options. This will then use a specify model for that session. This is very useful if you wish to start the agy session in an autonomous mode i.e. via the --prompt option. Take a look at the command-line options discussed later in this blog.&lt;/p&gt;

&lt;h4&gt;
  
  
  Antigravity CLI Reference (List of Commands and Shortcuts)
&lt;/h4&gt;

&lt;p&gt;What are the commands and keyboard shorcuts Antigravity CLI. The command as expected /help is your friend. Alternately, you can just type a ? to get this list.&lt;/p&gt;

&lt;p&gt;Try it out to see the range of commands available and learn a few shortcuts to navigate the terminal easily.&lt;/p&gt;

&lt;p&gt;Here are all 34 commands available in 1.0.1 at the time of writing. Try out a few if you’d like. We will cover several of them as we go along in the series.&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%2Fmszhnx16g0es5789ywa0.png" class="article-body-image-wrapper"&gt;&lt;img 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%2Fmszhnx16g0es5789ywa0.png" width="800" height="412"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Changelog
&lt;/h4&gt;

&lt;p&gt;Antigravity CLI is likely to undergo rapid changes. We saw that with Gemini CLI earlier, where there were almost daily updates. While we cannot predict the velocity of the releases, its good to know what is changing across the releases via the /changelog command. We are already seeing a good list of changes between the current version 1.0.1 vs 1.0.0 as shown 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.amazonaws.com%2Fuploads%2Farticles%2F0ul78n50dv85vvk14hrp.png" class="article-body-image-wrapper"&gt;&lt;img 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%2F0ul78n50dv85vvk14hrp.png" width="800" height="587"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Exit Antigravity CLI
&lt;/h4&gt;

&lt;p&gt;This can be done via the /quit command. If you are having difficulty to get to the prompt input, use esc esc to come out where you are.&lt;/p&gt;

&lt;p&gt;Whenever you exit, you will see the command that is needed to continue the conversation. As an example, this is what I received. If you do that, you can resume the conversation and will have an entire list of prompts that you gave. Just use Arrows Keys (up and down) in the prompt to see the history.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Resume: agy &lt;span class="nt"&gt;--conversation&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;bbb2048c-7de6-4dd5-ba7e-8b0c27d46b95 &lt;span class="o"&gt;(&lt;/span&gt;or &lt;span class="nt"&gt;-c&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Shell mode
&lt;/h3&gt;

&lt;p&gt;This is similar to Gemini CLI and you can enter into a Shell mode, such that you can give shell commands without the need to exit Antigravity CLI and come back again to it.&lt;/p&gt;

&lt;p&gt;Simply use the ! to go into Shell mode. You will notice that the prompt prefix will change from &amp;gt; to ! as shown 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.amazonaws.com%2Fuploads%2Farticles%2Fmo388qgh0ks8y0y2rbvl.png" class="article-body-image-wrapper"&gt;&lt;img 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%2Fmo388qgh0ks8y0y2rbvl.png" width="780" height="184"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can give commands like ls, pwd and other utilities that you might have too.&lt;/p&gt;

&lt;h3&gt;
  
  
  Our first coding task
&lt;/h3&gt;

&lt;p&gt;I am going to create a folder inside of agy-cli-projects and start my Antigravity CLI inside of that. I have named the folder bq-release-notes since I am going to create a BigQuery Release Notes Reader application.&lt;/p&gt;

&lt;p&gt;Let’s give Antigravity CLI our first task and ask it to build a web application that displays the content of a current RSS feed. Let’s say that I am very much interested in BigQuery Release notes. There is a &lt;a href="https://docs.cloud.google.com/feeds/bigquery-release-notes.xml" rel="noopener noreferrer"&gt;RSS Feed&lt;/a&gt; for it.&lt;/p&gt;

&lt;p&gt;I would like a web application in my prefered stack to be build to access this feed and show me the information.&lt;/p&gt;

&lt;p&gt;I begin with the following prompt:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Please build a web application for me using Python Flask and plain vanilla HTML, JavaScript and CSS that fetches the BigQuery Release notes from (&lt;a href="https://docs.cloud.google.com/feeds/bigquery-release-notes.xml" rel="noopener noreferrer"&gt;https://docs.cloud.google.com/feeds/bigquery-release-notes.xml&lt;/a&gt;) and shows them to me. A simple refresh button with a spinner is good enough, anytime I’d like to refresh the details. I would also like the ability to take any specific update, select it and then Tweet about it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This results in the following response from Antigravity CLI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  I will start by exploring the workspace to see if there is an existing structure or if this is a brand new project.                                                                    

● ListDir(/Users/romin/agy-cli-projects/bq-release-notes) (ctrl+o to expand)

  I will read the BigQuery release notes XML feed to understand its structure (Atom/RSS elements, entry/item elements, namespaces, dates, titles, content) so that we can parse it       
  correctly in the Python Flask backend.                                                                                                                                                 

● ReadURL(https://docs.cloud.google.com/feeds/bigquery-release-notes.xml) (ctrl+o to expand)

  I will view the fetched feed content saved locally to understand its format and structure.                                                                                             

● Read(/Users/romin/.gemini/antigravity-cli/brain/116191af-e6ea-4ba5-aa23-62f995bd068a/.system_generated/steps/6/content.md) (ctrl+o to expand)

▸ Thought for 2s, 2.3k tokens
  Analyzing XML Feed Structure
  I will write the implementation plan detailing the architecture, design aesthetic, components, and verification steps for the BigQuery Release Notes Web Application. This plan will be
  written to the artifacts directory.                                                                                                                                                    

● Create(/Users/romin/.gemini/antigravity-cli/brain/116191af-e6ea-4ba5-aa23-62f995bd068a/implementation_plan.md) (ctrl+o to expand)

  I have created the implementation_plan.md to outline the design and architecture of the BigQuery Release Notes Web Application.

  Please review the plan, especially the approach for the Twitter Composer &amp;amp; Preview Card, and let me know if you approve or if there are any adjustments you'd like to make!            

                                                                                                                                                            1 artifact · /artifact to review
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Remember that behind the scenes, you get the same Antigravity harness and if you are familiar with Antigravity, you can see that it has created an artifact (file) for us to view. Artifacts are how the Antigravity CLI keeps us in the loop with an implementation plan, list of tasks that it is working on, verifiable outputs and more.&lt;/p&gt;

&lt;p&gt;In this case, if you notice, it says and I quote &lt;strong&gt;“I will write the implementation plan detailing the architecture, design aesthetic, components, and verification steps for the BigQuery Release Notes Web Application. This plan will be written to the artifacts directory.”&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Once it does that, it says “ I have created the implementation_plan.md to outline the design and architecture of the BigQuery Release Notes Web Application. Please review the plan, especially the approach for the Twitter Composer &amp;amp; Preview Card, and let me know if you approve or if there are any adjustments you’d like to make!”&lt;/p&gt;

&lt;p&gt;You can see that it also mentions in the bottom right, that there is 1 Artifact to review and in this case, it is the implementation_plan.md.&lt;/p&gt;

&lt;p&gt;Now remember, this is all in the terminal, so we will have to use that and see how it goes. It’s pretty neat if you ask me.&lt;/p&gt;

&lt;p&gt;Give the command /artifact. This will display the following:&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%2F6598ioo97abtbax3oqvf.png" class="article-body-image-wrapper"&gt;&lt;img 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%2F6598ioo97abtbax3oqvf.png" width="799" height="89"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This clearly shows that there is a file implementation_plan.md created and I can use the arrow keys to open, approve, reject and so on. This should be familiar to those who have used earlier or even the recent version of Antigravity (the non-CLI app).&lt;/p&gt;

&lt;p&gt;On opening it, I can see the entire artifact i.e. Implementation plan.&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%2Fir4is5ke7ztm0u4xnzt0.png" class="article-body-image-wrapper"&gt;&lt;img 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%2Fir4is5ke7ztm0u4xnzt0.png" width="800" height="474"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Just Escape and come back to the prompt, here you can approve it , if you’d like:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frk9n4lx595lmmqn1a0xs.png" class="article-body-image-wrapper"&gt;&lt;img 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%2Frk9n4lx595lmmqn1a0xs.png" width="799" height="78"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Alternately, you can reject or even converse with some changes or modifications that you like. For e.g. we will go full vibe mode and say approve.&lt;/p&gt;

&lt;p&gt;This kicks off the next set of steps, where it will start the implementation i.e. creating files, running a few commans, etc. You will be prompted to approve and give permission to execute, as required.&lt;/p&gt;

&lt;p&gt;In my case, I gave it the approval to create the Python virtual environment, install the dependencies via requirements.txt and so on.&lt;/p&gt;

&lt;p&gt;In the background, it has also created a task.md file as part of the tasks that it has to do based on the implementation plan and it ticks off the individual tasks, as it completes them. You will just have to pay attention to the thought process and the tasks as it completes them. It makes for a fascinating experience.&lt;/p&gt;

&lt;p&gt;Finally I get the message that I wanted to see:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I have successfully completed the implementation of the BigQuery Release Pulse web application!&lt;/p&gt;

&lt;p&gt;The application dev server is up and running locally at &lt;a href="http://127.0.0.1:5000." rel="noopener noreferrer"&gt;http://127.0.0.1:5000.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Please refer to the walkthrough.md for details on the architectural implementation, the features we delivered, and verified test scenarios.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I also see that there are several artifacts as expected (Implementation Plan, Task List and a Walkthrough document)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Action required (3 left)
› task.md open 
  walkthrough.md
  □ new implementation_plan.md

  Media · 1 items (enter to expand)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If I look at the Task artifact, I get the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; task.md 
&amp;gt; 1 Tasks                                                                                                                                     
    2                                                                                                                                                
    3 [✓] Setup dependencies and environment                                                                                                     
    4 [✓] Implement backend Flask application ( app.py )                                                                                         
    5 [✓] Implement frontend HTML structure ( templates/index.html )                                                                             
    6 [✓] Implement frontend CSS styling ( static/css/style.css )                                                                                
    7 [✓] Implement frontend JS logic ( static/js/app.js )                                                                                       
    8 [✓] Verify local execution and manual test scenarios                                                                                       
    9 [✓] Create walkthrough documentation ( walkthrough.md )        
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Good work.&lt;/p&gt;

&lt;p&gt;I check the application in my browser and here it is. It looks great with a lot of features already thought out:&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%2F0imy7gmcazorcpycmruk.png" class="article-body-image-wrapper"&gt;&lt;img 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%2F0imy7gmcazorcpycmruk.png" width="800" height="438"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here’s my Tweet feature too:&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%2F6r2klwdnc0rms279xa38.png" class="article-body-image-wrapper"&gt;&lt;img 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%2F6r2klwdnc0rms279xa38.png" width="800" height="754"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I can go on now with new features, some changes, etc. But we can stop for now. The idea was to demonstrate and check out what it can do with simple requirements.&lt;/p&gt;

&lt;h3&gt;
  
  
  Our first non-coding Task
&lt;/h3&gt;

&lt;p&gt;Go to &lt;a href="https://github.com/rominirani/gemini-cli-codelab-projects" rel="noopener noreferrer"&gt;https://github.com/rominirani/gemini-cli-codelab-projects&lt;/a&gt; and check out the folder &lt;a href="https://github.com/rominirani/gemini-cli-codelab-projects/tree/main/invoice-processing" rel="noopener noreferrer"&gt;invoice-processing&lt;/a&gt; folder that has several invoices in the form of images.&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%2Fm5fdb1sda8bdr7h9bt95.png" class="article-body-image-wrapper"&gt;&lt;img 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%2Fm5fdb1sda8bdr7h9bt95.png" width="434" height="342"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let’s create a new folder inside of agy-cli-projects named invoice-processing. Download the four files into that folder and launch Antigravity CLI from there. You can take a peek into any of the invoices. One of the files is shown below (its an image):&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%2F6y99txpurd4ca1uxae79.png" class="article-body-image-wrapper"&gt;&lt;img 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%2F6y99txpurd4ca1uxae79.png" width="800" height="1134"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can use the Shell mode ( ! ) and then use the ls command to verify if you see the four invoice files there.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;● ! ls
  ⎿ inv1.png
     inv2.png
     inv3.png
     inv4.png
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now give the following prompt:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Use &lt;strong&gt;@inv1.png&lt;/strong&gt; and extract the following invoice information in the form of a table: Invoice No, Invoice Date, Invoice Sent By, Due Date, Due Amount.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Notice that you can use @ and you will see a list of files that will come up and you can choose from them. In short, I am asking Antigravity CLI to analyze this image file and extract relevant information of the invoice that I am interested in.&lt;/p&gt;

&lt;p&gt;I get the following output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  Analyzing Invoice Contents
  Here is the extracted invoice information from inv1.png:                                                                                      

   Invoice No │ Invoice Date │ Invoice Sent By │ Due Date │ Due Amount
  ─────────────────────────────┼─────────────────────────────┼─────────────────────────────┼─────────────────────────────┼────────────────────────────
    01234 │ 11.02.2030 │ Adeline Palmerston │ 11.03.2030 │ $440
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I can even ask it to simply go through the folder and extract information from all the invoices present in the folder. Here is the prompt:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The current folder contains a list of invoice files in Image format. Go through all the files in this folder and extract the following invoice information in the form of a table: Invoice No, Invoice Date, Invoice Sent By, Due Date, Due Amount.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Here is the output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Here is the extracted invoice information from all four files in the folder:                                                                        

   File │ Invoice No │ Invoice Date │ Invoice Sent By │ Due Date │ Due Amount
  ─────────────────────┼──────────────────────┼────────────────────┼────────────────────────────────────────┼────────────────────┼────────────────────
   inv1.png │ 01234 │ 11.02.2030 │ Adeline Palmerston │ 11.03.2030 │ $440.00
   inv2.png │ US-001 │ 11/02/2019 │ East Repair Inc. │ 26/02/2019 │ $154.06
   inv3.png │ 123456789 (P.O. #) │ November 23, 2023 │ A Company With A Clever Name (docubee) │ November 30, 2023 │ $42.30
   inv4.png │ [123456] │ 12/9/2019 │ Company Name │ 1/8/2020 │ $971.56

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I could even go a bit different and ask it to highlight all invoices that are having payment date that has passed.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;list all files with .png extension in this folder. Extract the invoice information from it by reading them locally and display it in a table format containing the following column headers: : Invoice No, Invoice Date, Invoice Sent By, Due Date, Due Amount. Add a column at the end of the table that shows a red cross emoji in case the due date is in the past.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Here’s the output:&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%2Fmzynufwhmt7xhrxukiww.png" class="article-body-image-wrapper"&gt;&lt;img 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%2Fmzynufwhmt7xhrxukiww.png" width="795" height="80"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I suggest that you go ahead and try out all kinds of tasks that are non-coding related. Analyzing some files, organizing them and so on.&lt;/p&gt;

&lt;h3&gt;
  
  
  Schedule an instruction
&lt;/h3&gt;

&lt;p&gt;You can use the /schedule command to automate recurring tasks or set one-time reminders.&lt;/p&gt;

&lt;p&gt;Let’s see how things work, when we just give the /schedule command. I get the following helpful reply:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/schedule

  Would you like to set up a recurring cron schedule or a one-time timer?                                                                             

  Please specify:                                                                                                                                     

  1. The timing: E.g., a duration in seconds (up to 900) or a cron expression (e.g., */5 * * * * ).                                                  
  2. The prompt: What task or reminder you want to run when it fires.                 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I go ahead and ask it to do a one-minute timer and then remind me that there is a meeting:&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; A one-time timer

  For how many seconds (up to 900 seconds/15 minutes) should the timer run, and what reminder message (prompt) should be triggered when it fires?     

────────────────────────────────────────────────────────────
&amp;gt; In 1 minute, remind me that there is a meeting

○ Schedule() (ctrl+o to expand)

  I have set a 1-minute timer for you. I will notify you as soon as it fires.       
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, you can get back to your work with Antigravity CLI. Once the timer is up, it should fire and let you know. And yes , in a minute, I got this message:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; ⏰ Reminder: There is a meeting starting now!     
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here are some examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A Pomodoro Timer that you can set and then get back to work. It will then remind you that time is up.
/schedule duration=”600" prompt=”Remind me that the current task time is over”&lt;/li&gt;
&lt;li&gt;In 3 minutes, run the following to check if migrations are successfully applied:
/schedule duration=”180" prompt=”Run ‘npm run db:status’ to verify if all migrations were successfully applied.”&lt;/li&gt;
&lt;li&gt;Here is one to check the logs in some time and see if there are any new errors:
/schedule duration=”600" prompt=”Inspect the logs folder and check if there are any new error entries or uncaught exceptions.”&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can also do a recurring (Cron expression) schedule to do a task. For e.g. do something at 9:00 AM every monday, or every 12 hours, etc. Here are some examples (I recommend that you substitute it with your commands, utilities and specific instructions):&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Standup Prep (Every weekday morning at 9:00 AM)&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;/schedule &lt;span class="nv"&gt;cron&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"0 9 * * 1–5"&lt;/span&gt; &lt;span class="nv"&gt;prompt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"Generate a bulleted summary of all git commits and file modifications made in the workspace in the last 24 hours."&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;End-of-Day Code Quality Check (Every weekday at 5:00 PM)&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;/schedule &lt;span class="nv"&gt;cron&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"0 17 * * 1–5"&lt;/span&gt; &lt;span class="nv"&gt;prompt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"Run 'npm test' and 'npm run lint' and report any test failures or code quality warnings."&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Local Server Health Check (Every 10 minutes)&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;/schedule &lt;span class="nv"&gt;cron&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"*/10 * * * *"&lt;/span&gt; &lt;span class="nv"&gt;prompt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"Check if the server running on http://localhost:3000 is still up and returning a 200 OK response."&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Hourly Folder Scan (Every hour)&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;/schedule &lt;span class="nv"&gt;cron&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"0 * * * *"&lt;/span&gt; &lt;span class="nv"&gt;prompt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"Scan the input directory for any new raw files, process them (put your rules here), and move them to the 'archive' folder."&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Weekly Dependency Update Audit (Every Friday at 4:00 PM)&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;/schedule &lt;span class="nv"&gt;cron&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"0 16 * * 5"&lt;/span&gt; &lt;span class="nv"&gt;prompt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"Run a security audit on project dependencies (e.g., 'npm audit' or 'pip-audit') and report any critical vulnerabilities."&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As an example, I setup a one-time 10 minute timer and then another recurring timer than runs every 10 mins.&lt;/p&gt;

&lt;p&gt;Once scheduled, I can interact in natural language with Antigravity CLI to find what tasks are running in the background. Just give a prompt like list my active tasks&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; list my active tasks

● ManageTask(You have 2 background task(s) currently running:) (ctrl+o to expand)

  Here are your currently active background tasks:                                                                                                    

  1. task-35                                                                                                                                         
      • Type: One-time Timer (600 seconds)                                                                                                            
      • Prompt: "Remind the user that the current task time is over."                                                                                 
      • Start Time: 2026-05-22T20:26:11 (Local time)                                                                                                  
  2. task-43                                                                                                                                         
      • Type: Recurring Cron ( */10 * * * * — every 10 minutes)                                                                                      
      • Prompt: "Check if the server running on http://localhost:3000 is still up and returning a 200 OK response."                                   
      • Start Time: 2026-05-22T20:33:29 (Local time) 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can now interact with it to even remove a task and so on.&lt;/p&gt;

&lt;h3&gt;
  
  
  We have a lot more to cover
&lt;/h3&gt;

&lt;p&gt;We have just scratched the surface at this point with Antigravity CLI. There are several commands to still try out, in addition to key things like configuring plugins, MCP Servers, skills, background tasks, parallel tasks, context management and more. Later parts of the tutorial will cover them.&lt;/p&gt;

&lt;h3&gt;
  
  
  Examine the Context
&lt;/h3&gt;

&lt;p&gt;You can visualize your context at any point in time via the /context command. A sample is shown 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.amazonaws.com%2Fuploads%2Farticles%2Fmwyma4fxn2td2wc053yz.png" class="article-body-image-wrapper"&gt;&lt;img 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%2Fmwyma4fxn2td2wc053yz.png" width="799" height="249"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  By the Way (btw)
&lt;/h3&gt;

&lt;p&gt;This is actually a command and a pretty useful one too. If you main agent is busy with some long running task, you can use the /btw command to ask it a side question. This does not interrupt the currently running task.&lt;/p&gt;

&lt;p&gt;The best way to try this would be by giving the Antigravity CLI a long running task like generating some application and then while it is busy, just give /btw  and see it in action.&lt;/p&gt;

&lt;p&gt;For example, the Agent is in the midst of refactoring the code and you would like to know about a specific git command. Give this instruction:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;/btw What is the git &lt;span class="nb"&gt;command &lt;/span&gt;to list branches sorted by last commit &lt;span class="nb"&gt;date&lt;/span&gt;?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;/btw what does &lt;span class="nb"&gt;exit &lt;/span&gt;status code 137 typically indicate?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here are few more things to know about /btw :&lt;/p&gt;

&lt;p&gt;• Parallel &amp;amp; Non-Interruptive: If the agent is currently busy running a long build script or refactoring several files in the workspace, typing /btw does not pause, abort, or delay that process. The main agent task continues running in the background.&lt;/p&gt;

&lt;p&gt;• Ephemeral UI: The output is rendered in a temporary overlay panel (similar to a modal) directly in the terminal interface. When you close the panel (by pressing Enter or Esc ), the response vanishes.&lt;/p&gt;

&lt;p&gt;• No Side-Effects (Read-Only context): To ensure speed and safety, /btw operates in a read-only mode. It has full read access to the files and conversation state, but it cannot execute tools (e.g., writing files, running bash commands, or scheduling tasks).&lt;/p&gt;

&lt;p&gt;• Token Efficiency: The prompt and response of a /btw query are not appended to the primary conversation history. This prevents casual questions from inflating the conversation context window (context bloat).&lt;/p&gt;

&lt;h3&gt;
  
  
  Understanding Command-line parameters of Antigravity CLI
&lt;/h3&gt;

&lt;p&gt;When we launched Antigravity CLI, we simply used agy to launch it. It uses several defaults in terms of what it needs to do and then shows you the terminal in which you can proceed to give commands.&lt;/p&gt;

&lt;p&gt;In this section, we shall look at a few command line options, that are available to use, while launching Antigravity CLI at the command line.&lt;/p&gt;

&lt;p&gt;If you can’t wait, you can get the current list of command line parameters/options available to you by using the agy --help , agy help, or agy -h command. This shows the following list at the time of writing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;agy &lt;span class="nt"&gt;--help&lt;/span&gt;
&lt;span class="go"&gt;Usage of agy:
  --add-dir Add a directory to the workspace (repeatable) (default [])
  -c Short alias for --continue
  --continue Continue the most recent conversation
  --conversation Resume a previous conversation by ID
  --dangerously-skip-permissions Auto-approve all tool permission requests without prompting
  -i Short alias for --prompt-interactive
  --log-file Override CLI log file path
  --model Model for the current CLI session
  -p Short alias for --print
  --print Run a single prompt non-interactively and print the response
  --print-timeout Timeout for print mode wait (default 5m0s)
  --prompt Alias for --print
  --prompt-interactive Run an initial prompt interactively and continue the session
  --sandbox Run in a sandbox with terminal restrictions enabled

Available subcommands:
  changelog Show changelog and release notes
  help Show help for subcommands
  install Configure environment paths and shell settings
  models List available models
  plugin Manage plugins (install, uninstall, list, enable, disable)
  plugins Alias for plugin
  update Update CLI
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So far we have launched Antigravity CLI and have been using it in interactive mode. If you’d like Antigravity CLI to just take your prompt, execute it and give back the result., then go for the &lt;strong&gt;non-interactive&lt;/strong&gt; mode. This is done via the --prompt parameter or via -p or --print parameter.&lt;/p&gt;

&lt;p&gt;This can be very useful in scenarios where you want to integrate Antigravity CLI in automated pipelines or schedule something at a specific time, without the need for any human interface.&lt;/p&gt;

&lt;p&gt;agy -p "What is the command line syntax for doing a GET call to myhost.com via curl"&lt;/p&gt;

&lt;p&gt;This might be a good way to get some quick answers but do keep in mind that &lt;strong&gt;there is be no scope to continue the conversation with follow up questions&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If you like to live dangerously (I do not), then you can look for a very aptly named parameter called --dangerously-skip-permissions.&lt;/p&gt;

&lt;p&gt;Launch Antigravity CLI via the following command:&lt;/p&gt;

&lt;p&gt;agy --dangerously-skip-permissions&lt;/p&gt;

&lt;p&gt;Then give the following prompt. Check that it did not ask me for any write file permissions.&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; get the latest news and write it in a file called news.txt. Then create another file that contains the summary of that file.

● ListDir(/Users/romin/agy-cli-projects) 
● WebSearch(latest world news May 24 2026 news headlines) (ctrl+o to expand)

▸ Thought for 2s, 95 tokens
  Processing News Information

● Create(/Users/romin/agy-cli-projects/news.txt) 
● Create(/Users/romin/agy-cli-projects/summary.txt) (ctrl+o to expand)

  I have fetched the latest world news headlines and created the requested files in your workspace:                                                                   

  1. news.txt: Contains the detailed news headlines for today (May 24, 2026), including topics on geopolitics (U.S.-Iran negotiations, Ukraine conflict), U.S.  
  security incidents, the Ebola outbreak in Central Africa, and the passing of NASCAR champion Kyle Busch.                                                            
  2. summary.txt: Contains a concise, structured summary of the major categories covered in the news file.                                                         

● ! ls
     news.txt
     summary.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This mode can be useful in scenarios where things are local and in your control but still be prepared for surprises and hence use it with care.&lt;/p&gt;

&lt;h4&gt;
  
  
  Specifying a model to use for the session
&lt;/h4&gt;

&lt;p&gt;You can use the --model parameter to tell Antigravity CLI to use a specific model during its session only. This is very useful for the autonomous mode that we discussed, where you would like to launch several agy sessions and use specific models for specific tasks.&lt;/p&gt;

&lt;p&gt;But first, you need to know which models are available for Antigravity CLI. You can do that via the models subcommand as shown below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;agy models
&lt;span class="go"&gt;Gemini 3.5 Flash (Medium)
Gemini 3.5 Flash (High)
Gemini 3.5 Flash (Low)
Gemini 3.1 Pro (Low)
Gemini 3.1 Pro (High)
Claude Sonnet 4.6 (Thinking)
Claude Opus 4.6 (Thinking)
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can use any of these model names to specify the model to be used for the session. You can do that via the --model command shown below:&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="nv"&gt;$ &lt;/span&gt;agy &lt;span class="nt"&gt;--model&lt;/span&gt; &lt;span class="s2"&gt;"Claude Opus 4.6 (Thinking)"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once Antigravity CLI launches, you can check either via the /model command about the specific model that you asked it to use or look at the bottom right that shows the model used for the session. An example is shown 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.amazonaws.com%2Fuploads%2Farticles%2Fddpd7jbkivxb1e3r283z.png" class="article-body-image-wrapper"&gt;&lt;img 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%2Fddpd7jbkivxb1e3r283z.png" width="800" height="248"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  More command-line options
&lt;/h4&gt;

&lt;p&gt;We will cover c , continue , conversation parameters in a separate part in this series, but will keep adding more information on command line parameters here, as Antigravity CLI takes shape. If you’d like to learn more about Conversations, check out &lt;a href="https://dev.to/iromin/antigravity-cli-tutorial-series-part-2-conversations-conversations-and-conversations-j39"&gt;Part 2&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Transitioning from Gemini CLI to Antigravity CLI
&lt;/h3&gt;

&lt;p&gt;If you have been using Gemini CLI, here are a few things that you need to understand.&lt;/p&gt;

&lt;p&gt;First up, you are not going to lose any of favourite workflows. Antigravity CLI to a large extent retains most of the features that you have been used to from Gemini CLI. Since it is early days yet, it is expected that the product team will use this time to probably get more parity based on user feedback. When it comes to Antigravity CLI, note that at the start of the article, we highlighted its key points about parallel execution, shared backend harness of Antigravity 2.0 and faster execution times.&lt;/p&gt;

&lt;p&gt;If you have been using a personal account with Gemini CLI, here are a few dates and events to keep in mind:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;June 18, 2026:&lt;/strong&gt; This is the hard cutoff for individual and free-tier users. On this date, the Gemini CLI and Gemini Code Assist IDE extensions will stop serving requests.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Please read the following blogs for more details on what will work or not, post June 18 2026 , especially if you are using a personal account.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://developers.googleblog.com/an-important-update-transitioning-gemini-cli-to-antigravity-cli/" rel="noopener noreferrer"&gt;An important update: Transitioning Gemini CLI to Antigravity CLI&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It is also important to understand a few changes from Gemini CLI, especially when it comes to configuration files that you were used to editing while tweaking and setting things up. This is critical since you might be having Extentions, MCP Servers, Skills and Context files that you were using with Gemini CLI.&lt;/p&gt;

&lt;p&gt;Check out this section of the document on &lt;strong&gt;Migrating&lt;/strong&gt; , that helps you understand what Antigravity CLI can directly import and use and a few key differences.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://antigravity.google/docs/gcli-migration" rel="noopener noreferrer"&gt;Google Antigravity&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;Thanks for reading this tutorial. This is just an initial introduction to help maximum number of users get started with Antigravity CLI. I will cover more parts in detail, as we move along.&lt;/p&gt;




</description>
      <category>antigravity</category>
      <category>antigravitycli</category>
      <category>tutorial</category>
      <category>googleantigravity</category>
    </item>
    <item>
      <title>Google Cloud Platform Technology Nuggets — May 1–15, 2026</title>
      <dc:creator>Romin Irani</dc:creator>
      <pubDate>Fri, 15 May 2026 04:50:41 +0000</pubDate>
      <link>https://dev.to/iromin/google-cloud-platform-technology-nuggets-may-1-15-2026-3p0g</link>
      <guid>https://dev.to/iromin/google-cloud-platform-technology-nuggets-may-1-15-2026-3p0g</guid>
      <description>&lt;p&gt;Welcome to the May 1–15, 2026 edition of Google Cloud Platform Technology Nuggets. The nuggets are also available on &lt;a href="https://www.youtube.com/playlist?list=PLiW95NS9M7-YaTpO0xL-ICabJvyolU-_s" rel="noopener noreferrer"&gt;YouTube&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.amazonaws.com%2Fuploads%2Farticles%2Fxdmhsufh8bge4z3fwn94.png" class="article-body-image-wrapper"&gt;&lt;img 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%2Fxdmhsufh8bge4z3fwn94.png" width="800" height="447"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Infographic for this post, generated by NotebookLM&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  AI and Machine Learning
&lt;/h3&gt;

&lt;p&gt;Gemini 3.1 Flash-Lite is now generally available on the Gemini Enterprise Agent Platform. It is a model specifically optimized for ultra-low latency and high-volume production deployments. This addition to the Gemini 3 series focuses on providing precision for agentic tasks such as tool calling, orchestration, and automated pipeline execution while minimizing operational costs. Check out the &lt;a href="https://cloud.google.com/blog/products/ai-machine-learning/gemini-3-1-flash-lite-is-now-generally-available?e=48754805" rel="noopener noreferrer"&gt;blog post&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.amazonaws.com%2Fuploads%2Farticles%2F0ay60ee3egljxa1z9yz8.png" class="article-body-image-wrapper"&gt;&lt;img 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%2F0ay60ee3egljxa1z9yz8.png" width="800" height="399"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In a mid-cycle update of the Gartner® Magic Quadrant™ for AI Application Development Platforms, Google has been &lt;a href="https://cloud.google.com/blog/products/ai-machine-learning/google-named-a-leader-in-the-gartner-magic-quadrant?e=48754805?utm_source%3Dlinkedin" rel="noopener noreferrer"&gt;given&lt;/a&gt; the #1 ranking across the three use cases assessed in the associated Critical Capabilities report. Download a complimentary copy of the 2026 Gartner Magic Quadrant update &lt;a href="https://cloud.google.com/resources/content/2025-gartner-mq-cc-ai-application-development-platforms?e=48754805" rel="noopener noreferrer"&gt;here&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.amazonaws.com%2Fuploads%2Farticles%2F05ams0bscxmibg60zob2.png" class="article-body-image-wrapper"&gt;&lt;img 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%2F05ams0bscxmibg60zob2.png" width="800" height="894"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Data Analytics
&lt;/h3&gt;

&lt;p&gt;While AI-powered SQL functions are a solid addition to the databases, cost and latency of these functions is a critical factor. An interesting approach called proxy models is now available, which are lightweight classifiers like logistic regression that replace the majority of expensive LLM calls during query execution. These models work by leveraging existing Gemini embeddings of data to identify semantic patterns, allowing the system to perform tasks like binary classification (AI.IF) or multiclass classification (AI.CLASSIFY) on the CPU rather than specialized hardware. The process involves an automated workflow where the engine samples a small portion of data, labels it using an LLM, trains a specialized proxy model on-the-fly, and evaluates its accuracy before deciding whether to use the proxy or the full LLM. This optimization is currently available in BigQuery and AlloyDB. Check out the &lt;a href="https://cloud.google.com/blog/products/data-analytics/more-than-100x-faster-and-cheaper-llm-powered-sql-queries-with-proxy-models" rel="noopener noreferrer"&gt;blog post&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.amazonaws.com%2Fuploads%2Farticles%2Fkluewtcumfif07ulacti.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkluewtcumfif07ulacti.jpg" width="800" height="250"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Databases
&lt;/h3&gt;

&lt;p&gt;The Database Center has been infused with several AI-driven updates to assist with the management of large-scale database fleets. The platform now features Gemini-powered intelligence for fleet-wide performance analysis, a natural language chat interface for troubleshooting across services like Cloud SQL and Spanner, and a testing agent to validate the impact of recommendations on latency and throughput before they are applied. Technical enhancements include public APIs integrated with the Model Context Protocol (MCP) for developer tool integration, centralized slow query analysis, and the inclusion of BigQuery inventory and data affiliation to map dependencies between transactional and analytical systems. Check out the &lt;a href="https://cloud.google.com/blog/products/databases/database-center-improvements-from-next26" rel="noopener noreferrer"&gt;blog post&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.amazonaws.com%2Fuploads%2Farticles%2Fvhj1cf0iud0thzsbycsp.png" class="article-body-image-wrapper"&gt;&lt;img 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%2Fvhj1cf0iud0thzsbycsp.png" width="800" height="456"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Bigtable has introduced Bigtable in-memory tier, a new feature within the Enterprise Plus edition designed to provide sub-millisecond read latency by using a hybrid storage architecture. This tier utilizes Remote Direct Memory Access (RDMA) to transfer data directly from memory without involving the system’s CPU or operating system, which helps avoid performance bottlenecks during traffic spikes. It offers approximately 10x higher point read throughput per dollar compared to standard configurations and provides hotspot resistance by supporting up to 120,000 queries per second on a single row. Check out the &lt;a href="https://cloud.google.com/blog/products/databases/scaling-real-time-performance-with-bigtable-in-memory-tier?e=48754805" rel="noopener noreferrer"&gt;blog post&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;PostgreSQL 18 is now available in in &lt;a href="https://cloud.google.com/blog/products/databases/postgres-18-and-extended-support-for-legacy-versions-in-alloydb?e=48754805?utm_source%3Dlinkedin" rel="noopener noreferrer"&gt;AlloyDB&lt;/a&gt; alongside a new Extended Support offering for older versions. This update includes B-tree skip scans for faster data retrieval, parallel GIN index usage for JSON and full-text searches, and native UUIDv7 support for better indexing efficiency in distributed applications. The platform now allows for virtual generated columns to compute data on-the-fly without using additional disk space. For older versions ranging from PostgreSQL 14 to 17, Extended Support provides three additional years of critical security patches and bug fixes beyond the community end-of-life dates. Users can perform in-place major version upgrades to transition to these newer releases. Check out the &lt;a href="https://cloud.google.com/blog/products/databases/postgres-18-and-extended-support-for-legacy-versions-in-alloydb" rel="noopener noreferrer"&gt;blog post&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;As always, if you are looking to bookmark a single link that covers whats new in Google Data Cloud, check &lt;a href="https://cloud.google.com/blog/products/data-analytics/whats-new-with-google-data-cloud" rel="noopener noreferrer"&gt;this&lt;/a&gt; out.&lt;/p&gt;

&lt;h3&gt;
  
  
  Developers &amp;amp; Practitioners
&lt;/h3&gt;

&lt;p&gt;The Gemini Enterprise Agent Platform is squarely focused on running, scaling, governing and optimizing agents in production. To do that, requires some key guidance from Google Cloud and that is now available in the form of 5 guides that help transition AI agents from prototypes to production:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Long-Running Agents: Utilize Agent Runtime for maintaining state up to seven days, enabling checkpoint-and-resume and human-in-the-loop approval workflows.&lt;/li&gt;
&lt;li&gt;Agent Governance Stack: Implement a five-layer security framework using Agent Identity for isolation, Agent Registry for tool control, and Agent Gateway for policy enforcement.&lt;/li&gt;
&lt;li&gt;Multi-Agent Orchestration: Use the Agent Development Kit (ADK) to build graph-based workflows and coordinator-specialist patterns for complex task management.&lt;/li&gt;
&lt;li&gt;A2A and MCP Interoperability: Connect agents across organizations and data systems using Agent-to-Agent (A2A) and Model Context Protocol (MCP) standards.&lt;/li&gt;
&lt;li&gt;Atomic Agent Blueprints: Access pre-configured architectures in the Agent Garden to accelerate development and avoid manual design errors.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Check out the &lt;a href="https://cloud.google.com/blog/topics/developers-practitioners/five-guides-to-building-and-scaling-production-ready-ai-agents" rel="noopener noreferrer"&gt;blog post&lt;/a&gt; for more details.&lt;/p&gt;

&lt;p&gt;While most of the AI developer tools focus on coding, one of the challenges that remains is that of the outer loop and bridging the gap between local development and production deployment. The Gemini CLI Extension for CI/CD is a tool that is designed to do exactly that. Using the Model Context Protocol (MCP), the extension integrates with Gemini CLI, Claude Code, and Antigravity to automate both “inner loop” tasks, like rapid deployment to Cloud Run via buildpacks, and “outer loop” requirements, such as generating cloudbuild.yaml files and provisioning infrastructure. Key technical features include a pre-deployment security scan to prevent secret leakage, an automated application analysis for containerization, and the ability to provision Artifact Registry repositories and Cloud Build triggers through natural language prompts. For more details, check out the &lt;a href="https://cloud.google.com/blog/topics/developers-practitioners/ship-code-within-minutes-with-the-gemini-cli-devops-extension" rel="noopener noreferrer"&gt;blog post.&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.amazonaws.com%2Fuploads%2Farticles%2Fti836zjsyvtkhqx413bm.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fti836zjsyvtkhqx413bm.jpg" width="800" height="394"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Containers and Kubernetes
&lt;/h3&gt;

&lt;p&gt;Google Cloud has introduced an architectural update to Google Kubernetes Engine (GKE) that reduces node startup times by up to 4x to address cold-start latency. This improvement is achieved by reworking node provisioning logic through a combination of intelligent compute buffers, fast-starting virtual machines, and a control plane that allows for instant VM resizing without reboots. These technical changes aim to reduce the need for over-provisioning and improve the scaling of AI inference and batch processing workloads. The feature is currently available for GKE Autopilot and specific NVIDIA GPU hardware, including L4, A100, RTXPRO6000, and H100 nodes, as well as general-purpose compute. For more details, check out the &lt;a href="https://cloud.google.com/blog/products/containers-kubernetes/gke-node-startup-gets-faster?e=48754805?utm_source%3Dlinkedin" rel="noopener noreferrer"&gt;blog post&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.amazonaws.com%2Fuploads%2Farticles%2F2cfxo1q3ef4f35rlyxur.png" class="article-body-image-wrapper"&gt;&lt;img 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%2F2cfxo1q3ef4f35rlyxur.png" width="799" height="441"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Security and Identity
&lt;/h3&gt;

&lt;p&gt;Gartner has &lt;a href="https://cloud.google.com/blog/products/identity-security/google-named-a-leader-in-the-2026-gartner-magic-quadrant-for-cyberthreat-intelligence-technologies?e=48754805?utm_source%3Dlinkedin" rel="noopener noreferrer"&gt;named&lt;/a&gt; Google a Leader in the 2026 Magic Quadrant for Cyberthreat Intelligence Technologies. You can download the full 2026 Gartner® Magic Quadrant™ for Cyberthreat Intelligence Technologies &lt;a href="https://cloud.google.com/resources/content/2026-gartner-cyberthreat-intelligence-magic-quadrant?utm_source=cgc-blog&amp;amp;utm_medium=blog&amp;amp;utm_campaign=FY26-Q2-GLOBAL-STO191-website-dl-dgcsm-cti-mq26-175842&amp;amp;utm_content=website&amp;amp;utm_term=-" rel="noopener noreferrer"&gt;here&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.amazonaws.com%2Fuploads%2Farticles%2Fofoijmcqljjtojj28h0o.png" class="article-body-image-wrapper"&gt;&lt;img 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%2Fofoijmcqljjtojj28h0o.png" width="800" height="908"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The second Cloud CISO Perspectives for April 2026 is &lt;a href="https://cloud.google.com/blog/products/identity-security/cloud-ciso-perspectives-next-26-why-we-re-multicloud-and-multi-ai" rel="noopener noreferrer"&gt;out&lt;/a&gt;. This issue discusses a strategy centered on multicloud and multi-AI environments to address modern security needs. Key technical highlights include the use of Gemini-powered security agents that have reduced alert triage times from 30 minutes to 60 seconds and a new dark web intelligence capability with 98% accuracy. The issue also discusses features in the new Gemini Enterprise Agent Platform, that has an Agent Gateway for identity management, Model Armor for prompt sanitization, and automated Agent Identity verification.&lt;/p&gt;

&lt;p&gt;With the Wiz acquisition now complete and highlighted at Google Cloud Next 2026, most practitioners are looking forward to understand how it all comes together under a common platform. In the &lt;a href="https://cloud.google.com/blog/products/identity-security/cloud-ciso-perspectives-how-google-wiz-changes-multicloud-strategy-for-cisos" rel="noopener noreferrer"&gt;first Cloud CISO Perspectives for May 2026&lt;/a&gt;, the post highlights how the collaboration affects multicloud security and it discusses a strategy centered on developer enablement and automated defense. The collaboration combines Wiz’s cloud telemetry with Google Cloud AI logic to move toward near real-time vulnerability resolution and self-healing infrastructure.&lt;/p&gt;

&lt;p&gt;If you are looking to understand the evolving security risks for AI coding agents, this &lt;a href="https://cloud.google.com/blog/products/identity-security/beyond-source-code-the-files-ai-coding-agents-trust-and-attackers-exploit?e=48754805?utm_source%3Dlinkedin" rel="noopener noreferrer"&gt;article&lt;/a&gt; explains how the attack surface has expanded beyond source code to include the files these agents trust. Threat actors are now targeting repository-level artifacts like tasks.json, settings.json, and Skill.md files to execute code, exfiltrate API keys, or redirect traffic to malicious endpoints by manipulating the agent’s semantic intent. Because these files often use natural language or valid configurations, they bypass traditional signature-based scanners. To counter this, Google Cloud highlights the use of VirusTotal Code Insight to perform semantic analysis, allowing defenders to identify high-risk instructions and hidden supply-chain threats within developer environments.&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%2F19i05kxwagdq5rjwbb5z.png" class="article-body-image-wrapper"&gt;&lt;img 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%2F19i05kxwagdq5rjwbb5z.png" width="800" height="435"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Infrastructure
&lt;/h3&gt;

&lt;p&gt;Google Cloud has &lt;a href="https://cloud.google.com/blog/products/compute/cluster-reliability-for-trillion-parameter-models-on-tpus" rel="noopener noreferrer"&gt;introduced&lt;/a&gt; a cluster-level reliability framework for Tensor Processing Units (TPUs) designed to support the training of trillion-parameter AI models.&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%2Fi9dd9oa0uhq4hg8u536r.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi9dd9oa0uhq4hg8u536r.jpg" width="799" height="495"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Storage
&lt;/h3&gt;

&lt;p&gt;If you are looking to address storage bottlenecks in AI and machine learning workflows, you now have Cloud Storage Rapid, a suite of high-performance object storage capabilities designed for data-heavy workloads. This family includes Rapid Bucket, a zonal storage option that provides sub-millisecond latency and up to 15 TB/s throughput to keep accelerators like GPUs and TPUs saturated, and Rapid Cache, which increases read bandwidth for existing buckets without requiring code changes. Check out the &lt;a href="https://cloud.google.com/blog/products/storage-data-transfer/cloud-storage-rapid-turbocharges-object-storage-for-ai-analytics" rel="noopener noreferrer"&gt;blog post&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.amazonaws.com%2Fuploads%2Farticles%2Fer8sevr8qygv738oxnhd.png" class="article-body-image-wrapper"&gt;&lt;img 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%2Fer8sevr8qygv738oxnhd.png" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Write for Google Cloud Medium publication
&lt;/h3&gt;

&lt;p&gt;If you would like to share your Google Cloud expertise with your fellow practitioners, consider becoming an author for Google Cloud Medium publication. Reach out to me via comments and/or fill out this&lt;a href="https://bit.ly/41CGNut" rel="noopener noreferrer"&gt;form&lt;/a&gt; and I’ll be happy to add you as a writer.&lt;/p&gt;

&lt;h3&gt;
  
  
  Stay in Touch
&lt;/h3&gt;

&lt;p&gt;Have questions, comments, or other feedback on this newsletter? Please send &lt;a href="https://forms.gle/UAsAS7YLxYSBTNBy9" rel="noopener noreferrer"&gt;Feedback&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If any of your peers are interested in receiving this newsletter, send them the&lt;a href="https://gcptechnuggets.substack.com/" rel="noopener noreferrer"&gt;Subscribe&lt;/a&gt; link.&lt;/p&gt;




</description>
      <category>googlecloudplatform</category>
      <category>gcptechnuggets</category>
      <category>gcpweekly</category>
    </item>
    <item>
      <title>[Boost]</title>
      <dc:creator>Romin Irani</dc:creator>
      <pubDate>Mon, 30 Mar 2026 11:23:30 +0000</pubDate>
      <link>https://dev.to/iromin/-2opg</link>
      <guid>https://dev.to/iromin/-2opg</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/gde/reflections-on-my-trainings-gemini-for-google-workspace-4fj3" class="crayons-story__hidden-navigation-link"&gt;Reflections on my Trainings: Gemini for Google Workspace&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;
          &lt;a class="crayons-logo crayons-logo--l" href="/gde"&gt;
            &lt;img alt="Google Developer Experts logo" 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%2Forganization%2Fprofile_image%2F11939%2Fe3080d5b-ecde-42a8-b089-bafecc31fa97.png" class="crayons-logo__image" width="800" height="800"&gt;
          &lt;/a&gt;

          &lt;a href="/aryanirani123" class="crayons-avatar  crayons-avatar--s absolute -right-2 -bottom-2 border-solid border-2 border-base-inverted  "&gt;
            &lt;img 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%2Fuser%2Fprofile_image%2F754479%2F1d1fdf42-b44b-4b4b-beba-7125aa2a60e7.jpeg" alt="aryanirani123 profile" class="crayons-avatar__image" width="800" height="533"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/aryanirani123" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Aryan Irani
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Aryan Irani
                
              
              &lt;div id="story-author-preview-content-3415350" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/aryanirani123" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img 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%2Fuser%2Fprofile_image%2F754479%2F1d1fdf42-b44b-4b4b-beba-7125aa2a60e7.jpeg" class="crayons-avatar__image" alt="" width="800" height="533"&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Aryan Irani&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

            &lt;span&gt;
              &lt;span class="crayons-story__tertiary fw-normal"&gt; for &lt;/span&gt;&lt;a href="/gde" class="crayons-story__secondary fw-medium"&gt;Google Developer Experts&lt;/a&gt;
            &lt;/span&gt;
          &lt;/div&gt;
          &lt;a href="https://dev.to/gde/reflections-on-my-trainings-gemini-for-google-workspace-4fj3" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Mar 28&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/gde/reflections-on-my-trainings-gemini-for-google-workspace-4fj3" id="article-link-3415350"&gt;
          Reflections on my Trainings: Gemini for Google Workspace
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/gemini"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;gemini&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/googleworkspace"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;googleworkspace&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/livetraining"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;livetraining&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/googleappsscript"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;googleappsscript&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/gde/reflections-on-my-trainings-gemini-for-google-workspace-4fj3" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/raised-hands-74b2099fd66a39f2d7eed9305ee0f4553df0eb7b4f11b01b6b1b499973048fe5.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/exploding-head-daceb38d627e6ae9b730f36a1e390fca556a4289d5a41abb2c35068ad3e2c4b5.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;13&lt;span class="hidden s:inline"&gt;&amp;nbsp;reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/gde/reflections-on-my-trainings-gemini-for-google-workspace-4fj3#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              &lt;span class="hidden s:inline"&gt;Add&amp;nbsp;Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            6 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
      <category>gemini</category>
      <category>googleworkspace</category>
      <category>livetraining</category>
      <category>googleappsscript</category>
    </item>
  </channel>
</rss>
