Friday, July 10, 2026

Developing Google Apps Script with serverless Antigravity harness engine in Managed Agents API

Do you also hate doing the same manual tasks in Google Workspace over and over again? Imagine just describing what you need in plain English, and boom - your spreadsheet automates itself like magic. With Antigravity, you can orchestrate automations directly, or let the agent write Google Apps Script for you. The real beauty of Apps Script is that it has built-in OAuth for Google services and runs serverless in the cloud. Your automations keep running serverless and in da cloud without your laptop even being turned on! :-)



You can define what you want directly in plain English and Antigravity writes the code. Even better, it can automatically deploy it using the clasp CLI (the command-line interface for Apps Script) so you don't have to copy-paste anything. The catch? To run this locally, you must keep your computer powered on. But who wants that? That's why we migrate the entire development flow into a serverless environment using the Managed Agents API!

BTW And have you heard the news? Google Apps Script was recently officially elevated to a Google Workspace core service! 🆕 This is huge! It means enterprise-grade data protection, administrative control, and standard technical support. 

Let's look at how this magic works under the hood! 😉

Here is how we move away from traditional line-by-line syntax to Vibe-Coding, where we set the high-level intent and the agent handles the heavy lifting

Step 1) Get ready with Antigravity

Instead of writing code, you just tell the agent in plain language: "Create a script that checks column B, and if it contains 'Cancelled', send an email to [email protected]." The agent acts as your

workspace developer, structuring the code, manifest, and configs automatically.

To get started, you need to download and install Antigravity. Personally, I run two setups: Antigravity IDE for my personal stuff (hooked up to my private Gmail account with a Google AI Pro license), and Antigravity 2.0 connected to a corporate Google Cloud Project. For this demo, we'll be using Antigravity IDE! 😉

Tip!

The black background icon is for Antigravity IDE, which was released in 11/2025
The white background icon is for Antigravity 2.0, which was introduced during in 5/2026.



Step 2) Prepare you environment

When you open Antigravity IDE for the first time, select your project folder. On the right-hand side, you'll see a panel where you can write instructions. And yes, you can execute commands directly from this chat input


Run clasp login on your computer to authorize the CLI.

Just type:

Use clasp CLI to login



To avoid starting from scratch, I prepared several Skills,  structured markdown files (SKILL.md) that describe how the agent should run and invoke tools. I have prepared three custom skills for this project:

- apps-script-developer: acts as your Google Apps Script developer, handling OAuth credentials and deploying code via clasp cli
https://github.com/codeas/managed-antigravity-gas/tree/main/skills/apps-script-developer

- cloud-migrator: takes care of packaging the local workspace and migrating dev tasks to the cloud sandbox.
https://github.com/codeas/managed-antigravity-gas/blob/main/skills/cloud-migrator/SKILL.md

- system-manager:  Configures Python virtual environments and manages package installations to keep everything isolated and clean.
https://github.com/codeas/managed-antigravity-gas/blob/main/skills/system-manager/SKILL.md


You can install skills with terminal commands (if you feel like a pro)

npx skills add https://github.com/codeas/managed-antigravity-gas

But wait, there is an even easier way! You don't even have to type that terminal command. Since you are talking to an intelligent agent, you can just ask it in plain English: “Install skill into local folder from https://github.com/codeas/managed-antigravity-gas” and watch it configure itself. How neat is that?



Once added, Antigravity automatically recognizes that there is a dedicated environment configuration skill (system-manager) in your workspace and runs it immediately to configure your local setup. In our case, it handles the Python virtual environment (.venv) setup and installs all packages for you. Zero manual terminal commands needed!

Step 3) Configure the Gemini API

We need this key to call the Managed Agents API service. (Another route is using the Gemini Enterprise Agent Platform, formerly known as Vertex AI on Google Cloud, but we'll stick to the simpler Gemini API option today!). 

Just hop over to Google AI Studio to grab your API key (or create a new one), and save it into your  .env
 file under GEMINI_API_KEY.



Tip! 

Always set a hard limit on your monthly spend in your billing settings—whether it's $10, $100, or $1000. It's a lifesaver safety net just in case something goes wrong and your agent goes on an infinite loop! 🤪



Step 4) Local development with local Antigravity harness

Describe what you want to automate and watch the magic happen! Now we have everything ready! We can unleash Antigravity and let the agent use the installed skills, running locally on our computer via Gemini (using our API key), to create and deploy a brand new Google Apps Script.

How do we actually do this? Let's start with a quick, simple experiment. Just describe what you want in plain language. To keep things sweet and simple, let's start with:
create a new folder and write a google apps script in this folder. Script retrieves all labels from my Gmail”.

Here is a simple snippet the agent can generate and push for you:



You can visithttps://script.google.com/, where you will find the same Google Apps Script as well



Step 5) Cloud development with local Antigravity harness with Managed Agents API

Everything we've shown so far is the "classic" local developer loop, similar to what other tools like Claude Code do. But now, let's look at the real superpower of Antigravity and Google—it's like turning on the warp drive! What if you want to execute tasks completely off your local machine?

For this, we'll harness the Managed Agents API. It runs the exact same Antigravity environment in the cloud. You can use the standard remote agent, or customize it to your needs.

To keep it super simple, we'll use our pre-configured 

cloud-migrator skill. It reads your local workspace context and configuration, sends it to the cloud sandbox along with your prompt, executes the agent reasoning loop remotely, and performs the Apps Script deployment directly from there! All serverless.

Just run (instead of xxxxxxxxxxx, paste your apps script)
Migrate to cloud and execute: Improve google apps script xxxxxxxxxxxx to save all Gmail labels into a spreadsheet named 'labels-demo'.

Under the hood, this command triggers the cloud-migrator skill, which contains the exact blueprint of how to call the Managed Agents API. Once launched, the remote Antigravity agent spins up in a secure container in the cloud and executes your prompt completely on its own!



One super neat detail: when the cloud execution starts, the local agent tells you it's waiting for the remote task to finish and will notify you when it's done


Once the cloud run is complete, the local agent detects the remote changes and automatically merges them back into your local workspace files! 😉


Finally, you can check your Google Apps Script dashboard to verify that your script has updated and deployed correctly!





Summary


With this post, I wanted to inspire you on how to unleash the true power of Skills combined with the Managed Agents API to run tasks entirely in da cloud!

Beyond standard Python development, this setup is incredibly powerful for automating Google Apps Script inside your Google Workspace. You don't necessarily need complex, persistent frameworks like OpenClaw. By extending the concepts we explored, you can easily set up a cloud agent that you talk to directly via Google Chat, letting it build automations or automatically resolve bugs based on GitHub issues!

This is the beauty of serverless Ad-hoc skill execution engines and ephemeral compute patterns: you write reusable, portable Markdown execution protocols for ad-hoc agent tooling, letting the agent temporarily spin up secure environments for specific tasks without any ongoing server runtime or infrastructure headaches.

What do you think about this way of vibe-coding? Are you ready to take your Apps Script development to da cloud? Ping me on X @ivankutil or let me know on #LinkedinIn

#GoogleAppsScript #GeminiAPI #AntigravitySDK #WorkspaceAutomation #AISprint #AgenticArchitect #GoogleAntigravity 






Saturday, December 20, 2025

Building a Google Workspace Security Agent with ADK and Policy API

You might have Google Workspace configured perfectly for your startup or enterprise today. But configuration is not a one-time event; it's a neverending lifecycle. You need to verify if 2-Step Verification is truly enforced for everyone, or check which context-aware access levels are active. Clicking through the Google Admin Console to verify hundreds of settings is manual labor. 

How to create an agent with Gemini 3 (Flash) that will check the settings continuously?



Google has recently introduced the Policy API (part of Cloud Identity API), which lets you programmatically view settings that usually live deep inside the Google Workspace Admin Console UI.



Since I've been spending a lot of time with the Agent Development Kit (ADK) lately, I had an idea: Why not build a specific "Auditing Agent" to do the heavy lifting for me?



The Google Workspace Admin Console is great for setting things up, but difficult for auditing at scale. If you want to know "What is the security posture of the 'Marketing' group?", you have to dig deep. The official Policy API allows you to fetch all these policies programmatically. 




I built a Proof-of-Concept Security Agent (with ADK) that reads the API documentation (OpenAPI spec), authenticates securely (OAuth), and answers our questions directly with Gemini 3 Flash.

The Architecture recap
The setup is surprisingly simple. It is about connecting three things: 
1. Policy API: The source of truth for your policies. 
2. ADK (Agent Development Kit) The framework that handles the plumbing (OAuth, Tool calling).
3. Gemini 3 Flash:: The brain that interprets the policy data. 

Agent setup

I will describe my workflow how I did it.

I visited the Cloud Identity API documentation page, because Policy API is part of this endpoint






There is no OpenAPI specification directly here but it is described in Google Discover API - check this JSON file https://cloudidentity.googleapis.com/$discovery/rest?version=v1

So how to do it? I wrote a converter app in Google I Studio that converts JSON format to YAML as OpenAPI.

My prompt was
create an application to convert static google discovery specification to openapi 3 yaml format.
I will paste a google discovery format (as json) and get return in yaml (text)



Once I had the exported YAML file, I was ready for the next step. This file is the "secret sauce" of the whole setup. It serves as a bridge between the complex Policy API and our agent's decision-making process. In the world of AI, agents are essentially a Large Language Model (LLM) paired with a set of tools. While Gemini 3 Flash provides the "brain," the tools provide the "hands" to actually interact with your Google Workspace data.

Usually, you have to define these tools by writing individual Python functions. You’d write the code, add detailed docstrings, and then the agent would use those descriptions to figure out which function to call. It works, but it’s a lot of manual work if you’re dealing with a complex API.

The beauty of using a YAML (OpenAPI schema) definition is that you can skip the manual coding. Instead of writing a separate function for every single API endpoint, you simply provide the YAML file to the Agent Development Kit (ADK) (as seperate file in my case)
The agent is smart enough to parse the specification, understand the available endpoints, and know exactly what parameters are required for each request. It’s a much more efficient way to build, especially when you want your agent to have full access to a comprehensive API like the Policy API.

Since we’re dealing with sensitive organizational data, authentication is a critical piece of the puzzle. Google’s ADK provides built-in OAuth objects that handle the heavy lifting of user authorization.

I visited to the Google Cloud Console (http://console.cloud.google.com/auth/clients/) to generate an OAuth Client ID and OAuth Client Secret in Google Auth Platform.



The trick is to never hardcode these directly into your scripts. I store them in a .env file—it’s a simple way to keep your credentials secure and your code clean. 

Note: Model Gemini 3 Flash Preview is available in global region

.env ---


The agent.py file is where the magic happens. It contains the agent’s core definition (Agent()), including specific instructions provided through a prompt. I’ve clearly defined its role: what it should accomplish and which tools it needs to call upon to get the job done. I used best-practices for Gemini 3 prompting (eg. using <meta>tags</meta>


Next, I configured the OAuth flow. This involves specifying the authorization URL and the necessary scopes. For this auditing agent, I used the scope  https://www.googleapis.com/auth/cloud-identity.policies.readonly . We only need to read the data to analyze it; there's no need for write access, which follows the principle of least privilege.

The last step was setting up the redirect URI. For local testing, I pointed it to "http://localhost:8000/oauth-callback". Just a small heads-up: you must remember to add this local address to your allow-list in the Google Cloud Console. It’s a common stumbling block, but once that's in place, the authentication handshake works perfectly



agent.py ---
Run Agent

With the agent defined and OAuth ready, it was time to take it for a run. 

The Agent Development Kit makes this process incredibly easy with a single command: adk web. Running this in your shell launches a local development interface—a sandbox where you can talk to your agent and see how it thinks.


Once the ADK DEV UI is up, I started with a direct question: "Audit my Google Workspace." Because the agent needs to access live data, it immediately triggered the OAuth flow. I was redirected to a standard Google login screen. 

The beauty of this approach is that I didn't have to tell the agent how to call the API. It used the YAML definition to look up the correct endpoints in the Policy API, fetched the current configuration, and compared it against security best practices. It's like giving Gemini 3 a map and a set of keys, and letting it do the exploration for you.

The final result was exactly what I was looking for. Instead of digging through the Admin Console or parsing through raw JSON, I received a concise summary in natural language. The agent pointed out exactly which settings weren't aligned with my security goals.





Now you can audit your Google Workspace with one just specialized agents


Note: Google Cloud credits are provided for this project during #AISprint 



Monday, June 30, 2025

Vibe Scraping with Google Apps Script and Gemini's URL Context

Nine years ago, I wrote an article describing how to scrape data from the internet in about five minutes. It featured a Google Apps Script library that allowed you to specify what to download from a webpage by identifying the text surrounding your target information. This became one of my most-read articles, and the library itself saved me a significant amount of time.

With the advent of large language models like Gemini, this entire paradigm is shifting. Just as "vibe coding" describes a more intuitive approach to programming, I'd say we're now entering an era of "vibe-scraping." 

You simply define what information you want and URL, and the Gemini API handles the retrieval.The new features available in the Gemini API through Google AI Studio take this concept even further. 



Let's explore this with a practical example I have recently wanted to solve..

I maintain a list of movies I'm interested in watching in a Google Sheet. I want this sheet to include details like current ratings, genre, movie length, and other information typically found on ÄŒSFD (a popular movie database for Czech users, similar to IMDb).

It occurred to me: what if I could simply tell a model what information to fetch, and it would automatically populate the data, structured, into the respective cells in my spreadsheet?


1. This function is dedicated to interacting with the Gemini API. This refers to the API endpoint accessible through Google AI Studio


2. Extracting Structured Data from the URL.
Next second function then calls the Gemini API, utilizing the powerful URL Context parameter.https://ai.google.dev/gemini-api/docs/url-context
This parameter instructs Gemini to ground its responses on the actual content of the provided URL and significantly decreate the likelihood of the hallucinations.

I found that for simple text work, the Gemini 2.5 Flash model is sufficient.


4. To make this solution as universal as possible, I decided to define what information to extract using prompts in the first row of the Google Sheet.


For example, I'd have column headers like "Name", "Rating," "Genre," "Runtime," etc. This means a user can easily customize the data they want to pull by simply changing these header texts, without needing to modify any code. The script then reads these headers and instructs Gemini to find and place the corresponding information into the cells below for each movie.

In my case, I listed several pieces of information in the header row. The script then processes each movie title, finds its page, extracts the specified details using Gemini, and neatly places them into the correct cells in the Google Sheet. This approach elegantly combines the power of Gemini with the flexibility of Google Sheets for efficient, targeted web data extraction.






This approach elegantly combines the power of Gemini with the flexibility of Google Sheets for efficient, targeted web data extraction. You simply enter corresponding URL and the system works to populate your sheet. The script processes each movie entry, leveraging Gemini to extract the specified details, and automatically organizes them into your spreadsheet, streamlining what used to be a time-consuming manual or complex coding task.

Friday, February 28, 2025

Create AI agents in Google Apps Script with Vertex AI and Gemini




Imagine that you write in plain English what you want to do in Google Workspace (eg. workflows) and it happens just like magic. Insert text prompt, Gemini will generate the code for you and run it immediately. A dream? No, reality, thanks to my conceptual and practical idea of how to implement AI Agents in Google Apps Scripts to leverage the V8 runtime.



Google Apps Script


Google Apps Script lets you connect and automate Google Workspace services (like Gmail, Docs, and Drive) by writing JavaScript code in your browser, without needing a separate server. Until now, you had to know programming to create that code.

Gemini


Large Language Models (LLMs) like Gemini are revolutionizing how we interact with technology. Gemini can convert natural language instruction ("prompts") into executable code. Imagine simply describing what you want to automate in plain English, and Gemini generates the code for you.

Vertex AI

Google Cloud's Vertex AI platform offers a powerful tools for working with AI and machine learning models. The Vertex AI Reasoning Engine is a particularly interesting aspect. Its code interpreter allows to run generated code like it would be done in a local environment, but development requires a Python environment and it also becomes more complex to integrate into the Google Workspace environment via APIs. While testing, it occurred to me, could it be simpler?"

Introducing AI Agents for Google Apps Script

In this project, I explored creating a concept for AI Agents. Using a natural language you describe your need, this is then passed to Gemini, leveraging Gemini 2.0 Flash Thinking, to generate the necessary code. The generated code is then fed back into the Google Apps Script environment. The generated code can then execute as part of App Script.

You have to double-check before executing the code. To mitigate this potential risk, a "dry run" function can be included.  This sends the generated code to a smaller model, Gemini 2.0 Flash. The test compares what the code does compared to original task. The results from testing is presented in plain text for verification.




Explanation

1. Open Google Apps Script: The easiest way to start is to simply visit https://script.new in your browser. This will instantly create a new Apps Script project.



2.  You'll need to configure the Apps Script project's manifest file. The manifest defines the settings for your Apps Script project. The manifest specifies the permissions ("scopes") that your application will need to access Google services. Be sure to carefully select and authorize only the necessary scopes for your agent. If you get an error when running, it's because you don't have the necessary permissions and you need to add more scopes.



3. Now I have prepared a function that calls the Gemini API within Vertex AI.




Copy the code into a new .gs file within the Google Apps Script project."

This code describes running an agent. First, it must be configured using the GCP Project and region. Then, you describe in natural language what needs to be done. After running the .act() method, Gemini 2.0 Flash Thinking within Vertex AI is called to generate code.

To ensure that the agent is doing the right thing, you can test the execution via a dry-run, where the code is sent to an internal Tester agent who, via Gemini 2.0 Flash, comments on the code and summarizes it in a log.

If everything is in order, you can then run .run(). I remind you again that you have given the script rights to everything. So if you write something wrong, for example, to delete data, it will actually be deleted. I am not responsible for the results of the script, and you should always review it before running it.

The generated code is stored in the Cache, so after running a dry-run and then a run, the same version will be executed within the Cache limit (currently set to 5 minutes).

  
  ```javascript
  // Define the label name
  const labelName = 'DEMO';

  // Check if the label exists, create if not
  let demoLabel = GmailApp.getUserLabels().find(label => label.getName() === labelName); // Find the label by name
  if (!demoLabel) { // If the label doesn't exist
    demoLabel = GmailApp.createLabel(labelName); // Create the label
    Logger.log(`Label "${labelName}" created.`); // Log that the label was created
  } else { // If the label already exists
    Logger.log(`Label "${labelName}" already exists.`); // Log that the label already exists
  }

  // Load last 10 emails with subject 'Security alert'
  const threads = GmailApp.search('subject:"Security alert"', 0, 10); // Search for threads with the specified subject, starting from the first thread (0) and retrieving a maximum of 10 threads

  // Set the 'DEMO' label to found emails
  if (threads.length > 0) { // If any threads were found
    threads.forEach(thread => { // Iterate over each thread
      thread.addLabel(demoLabel); // Add the 'DEMO' label to the current thread
    });
    Logger.log(`Label "${labelName}" applied to ${threads.length} emails.`); // Log the number of emails the label was applied to
  } else { // If no threads were found
    Logger.log('No emails with subject "Security alert" found in the last 10 threads.'); // Log that no emails were found
  }
```

**Summary:**

The code functions exactly as described in the task:

1.  **Creates a new label 'DEMO' if it doesn't exist:** The code first checks if a label named 'DEMO' already exists. If not, it creates the label.
2.  **Loads the last 10 emails with the subject 'Security alert':** The code then searches for the last 10 emails that have the subject 'Security alert'.
3.  **Sets the 'DEMO' label to the found emails:** Finally, the code iterates through the found emails (represented as threads) and applies the 'DEMO' label to each of them.

The code also includes logging statements to provide information about the actions being performed, which is good practice.
  

Acknowledgments

This project was developed during the Vertex sprints organized by Google’s Developer Expert Program. Google Cloud credits were provided. Thanks, Google, for providing GCP credits for making this happen. #VertexAISprint