Welcome to the definitive guide on Google Cloud Agent Skills.
The Series:
- Part 1 : What are Google Cloud Skills
- Part 2 : Intermediate Skills in Action (BigQuery and Cloud Run) (this blog)
_- Part 3 : Advanced Ops (WAF Security, Architecture, Custom Skills)
- Part 4 : More Use Cases_
Before your agent or code can interact with any Google Cloud service, it needs permission to do so. Authentication is the very first step in the Google Cloud Agent Skills workflow because without it, every subsequent operation will fail with a 401 Unauthorized or 403 Forbidden error.
Setting up authentication correctly ensures a smooth, secure experience whether you are building locally, deploying to the cloud, or using agents.
Prerequisites: Manual Setup
While our agent will do most of the heavy lifting, authentication requires an initial manual login to establish your identity on your machine.
Run the following commands in your terminal:
# Set your active project
gcloud config set project YOUR_PROJECT_ID
# Login to the gcloud CLI
gcloud auth login
# Set up Application Default Credentials (ADC)
gcloud auth application-default login
Once this is done, you are ready to use the agent for everything else!
Confirming Skill Installation
For this step, we will use the google-cloud-recipe-auth skill. Confirm it's installed:
npx skills list
Prompt-Driven Authentication Checks
Instead of manually running diagnostic scripts or consulting complex decision trees, you can just ask your agent. The agent uses the google-cloud-recipe-auth skill to evaluate your environment and provide tailored guidance.
The responses given below are from running them in Antigravity CLI.
1. Verifying Authentication
You prompt: Check if my Google Cloud authentication is set up correctly for project YOUR_PROJECT_ID
Agent response:
Yes, your Google Cloud authentication is set up correctly for project PROJECT_ID.
### Verification Details:
1. Active Account (gcloud CLI)
• Account: YOUR_ACCOUNT
• Status: Authenticated & Active
2. Project Configuration
• Active Project: PROJECT_ID
• Quota Project: PROJECT_ID
• Compute Region: us-central1
3. Project Access & Status
• Project Name: PROJECT_ID
• Project Number: PROJECT_NUMBER
• Lifecycle State: ACTIVE
• Permissions: Verified (able to retrieve project metadata via Resource Manager API).
4. Application Default Credentials (ADC)
• Status: Active & Valid (client SDKs and application libraries can successfully authenticate to Google Cloud APIs).
2. Architectural Auth Decisions
You prompt: What authentication method should I use for a Cloud Run service that needs to access BigQuery?
Agent response: (Which skill did it use? Answer comes a bit later)
For a Cloud Run service accessing BigQuery, the recommended Google Cloud best practice is Service-to-Service Authentication via attached Service
Accounts.
──────
### Recommended Setup
#### 1. Authentication (Identity)
Attach a Custom User-Managed Service Account to your Cloud Run service instead of using default accounts or static JSON key files.
• Create a custom service account (e.g., cloud-run-bq-sa@<project-id>.iam.gserviceaccount.com).
• Attach it to Cloud Run during deployment:
gcloud run deploy SERVICE_NAME \
--image IMAGE_URL \
--service-account cloud-run-bq-sa@PROJECT_ID.iam.gserviceaccount.com
│ ⚠️ Avoid using static Service Account Keys (JSON files). Cloud Run provides a secure local metadata server that handles token issuance dynamically.
──────
#### 2. Authorization (IAM Roles)
Grant your service account the least-privilege IAM roles required for BigQuery:
• roles/bigquery.jobUser: Required to run query jobs in the project.
• roles/bigquery.dataViewer (or roles/bigquery.dataEditor): Required to read (or write) data in the specific dataset or tables.
# Grant permission to run jobs in the project
gcloud projects add-iam-policy-binding PROJECT_ID \
--member="serviceAccount:cloud-run-bq-sa@PROJECT_ID.iam.gserviceaccount.com" \
--role="roles/bigquery.jobUser"
# Grant permission on the dataset
gcloud bigquery datasets add-iam-policy-binding DATASET_NAME \
--member="serviceAccount:cloud-run-bq-sa@PROJECT_ID.iam.gserviceaccount.com" \
--role="roles/bigquery.dataViewer"
──────
#### 3. In-Code Access (Application Default Credentials)
In your application code, initialize the official Google Cloud BigQuery client library without passing explicit credentials. The library
automatically retrieves tokens via Application Default Credentials (ADC) from the Cloud Run metadata server.
Python Example:
from google.cloud import bigquery
# Automatically authenticates using the attached service account
client = bigquery.Client(project="PROJECT_ID")
query_job = client.query("SELECT 1 AS test")
results = query_job.result()
I asked Antigravity CLI the following question: how did you answer the above question?
And here is the response. Check how it used the other skill:
I answered the question by drawing on Google Cloud's Security Best Practices (documented in the SKILL.md skill):
1. Authentication Framework (Identity)
• Google Cloud recommends using managed service identities for production workloads rather than static credentials (like JSON key files).
• In Cloud Run, attaching a custom service account allows the instance metadata server to issue short-lived access tokens dynamically.
2. IAM Authorization Model (Permissions)
• Google Cloud IAM enforces the principle of least privilege.
• Accessing BigQuery requires separating job execution rights (roles/bigquery.jobUser) from data access rights (roles/bigquery.dataViewer or
dataEditor).
3. Application Default Credentials (ADC)
• Standard Google Cloud Client Libraries automatically search for credentials in a predefined hierarchy.
• On Cloud Run, ADC automatically retrieves tokens from the attached service account via the internal metadata server (http://169.254.169.254),
making hardcoded credentials unnecessary.
3. Setting up a Service Account
Try out things like this Help me set up a service account for my Cloud Run application with minimal permissions to access BigQuery
BigQuery Skills
In this step, we’ll explore how to use Agent Skills to interact with Google BigQuery. Instead of manually writing bash scripts, SQL queries, or Python clients, we will rely entirely on our AI agent.
Confirming Skill Installation
For this step, we will use the bigquery-basics skill. Confirm it's installed:
npx skills list
Prompt-Driven BigQuery Operations
With the bigquery-basics skill, the agent understands how to manage datasets, create tables, insert data, and run analytical queries.
1. Creating a Dataset
You prompt: Create a new BigQuery dataset called skills_tutorial in my project PROJECT_ID
Agent response:
The BigQuery dataset skills_tutorial has been successfully created in project PROJECT_ID.
### Dataset Details:
• Dataset ID: PROJECT_ID:skills_tutorial
• Location: US
• Type: DEFAULT
• Status: Active (Verified)
- Creating a Table
You prompt: Now create a table called web_analytics in that dataset with columns for: event_timestamp (TIMESTAMP), page_url (STRING), user_id (STRING), session_duration_seconds (FLOAT64), country (STRING)
Agent response:
The BigQuery table web_analytics has been successfully created in dataset skills_tutorial.
### Table Details:
• Table ID: PROJECT_ID:skills_tutorial.web_analytics
### Schema:
Column Name │ Type │ Mode
─────────────────────────────────────────────────┼─────────────────────────────────────────────────┼────────────────────────────────────────────────
event_timestamp │ TIMESTAMP │ NULLABLE
page_url │ STRING │ NULLABLE
user_id │ STRING │ NULLABLE
session_duration_seconds │ FLOAT64 │ NULLABLE
country │ STRING │ NULLABLE
3. Inserting Sample Data
You prompt: Insert 10 rows of realistic sample web analytics data into the web_analytics table
Agent response:
10 realistic sample rows have been inserted into PROJECT_ID:skills_tutorial.web_analytics.
### Inserted Data Preview:
event_timestamp │ page_url │ user_id │ session_duration_seconds │ country
───────────────────────────┼─────────────────────────────────────┼───────────────────────────┼───────────────────────────┼──────────────────────────
2026-07-23 10:15:30 UTC │ https://example.com/home │ usr_1001 │ 45.2 │ US
2026-07-23 10:18:12 UTC │ https://example.com/products/laptop │ usr_1002 │ 120.8 │ CA
2026-07-23 11:02:45 UTC │ https://example.com/blog/ai-trends │ usr_1003 │ 310.5 │ GB
2026-07-23 11:45:00 UTC │ https://example.com/cart │ usr_1001 │ 88.0 │ US
2026-07-23 12:30:15 UTC │ https://example.com/checkout │ usr_1004 │ 215.3 │ DE
2026-07-23 13:10:05 UTC │ https://example.com/home │ usr_1005 │ 15.6 │ IN
2026-07-23 14:05:22 UTC │ https://example.com/pricing │ usr_1006 │ 175.4 │ JP
2026-07-23 14:22:10 UTC │ https://example.com/docs/api │ usr_1007 │ 450.0 │ US
2026-07-23 15:00:50 UTC │ https://example.com/about │ usr_1008 │ 62.1 │ FR
2026-07-23 15:40:18 UTC │ https://example.com/contact │ usr_1009 │ 95.7 │ AU
4. Running Analytical Queries
You prompt: Query the web_analytics table to show me the top 5 countries by average session duration
Agent response:
Here are the top 5 countries by average session duration from the web_analytics table:
### Query Results:
Rank │ Country │ Average Session Duration (seconds) │ Total Sessions
─────────────────────────────────────┼────────────────────────────────────┼────────────────────────────────────┼────────────────────────────────────
1 │ United Kingdom (GB) │ 310.50 s │ 1
2 │ Germany (DE) │ 215.30 s │ 1
3 │ United States (US) │ 194.40 s │ 3
4 │ Japan (JP) │ 175.40 s │ 1
5 │ Canada (CA) │ 120.80 s │ 1
──────
### Executed SQL Query:
SELECT
country,
ROUND(AVG(session_duration_seconds), 2) AS avg_session_duration_seconds,
COUNT(*) AS total_sessions
FROM `PROJECT_ID.skills_tutorial.web_analytics`
GROUP BY country
ORDER BY avg_session_duration_seconds DESC
LIMIT 5;
5. Complex Aggregations
You prompt: Show me a query that calculates daily page view counts grouped by URL
Agent response:
Here is the SQL query to calculate daily page view counts grouped by URL, along with unique visitor metrics:
### SQL Query:
SELECT
DATE(event_timestamp) AS event_date,
page_url,
COUNT(*) AS page_views,
COUNT(DISTINCT user_id) AS unique_visitors
FROM `PROJECT_ID.skills_tutorial.web_analytics`
GROUP BY
event_date,
page_url
ORDER BY
event_date DESC,
page_views DESC;
──────
### Execution Results:
Event Date │ Page URL │ Page Views │ Unique Visitors
────────────────────────────────────┼─────────────────────────────────────┼────────────────────────────────────┼────────────────────────────────────
2026-07-23 │ https://example.com/home │ 2 │ 2
2026-07-23 │ https://example.com/products/laptop │ 1 │ 1
2026-07-23 │ https://example.com/blog/ai-trends │ 1 │ 1
2026-07-23 │ https://example.com/cart │ 1 │ 1
2026-07-23 │ https://example.com/checkout │ 1 │ 1
2026-07-23 │ https://example.com/pricing │ 1 │ 1
2026-07-23 │ https://example.com/docs/api │ 1 │ 1
2026-07-23 │ https://example.com/about │ 1 │ 1
2026-07-23 │ https://example.com/contact │ 1 │ 1
6. Cleanup
You prompt: Clean up i.e. delete the skills_tutorial dataset
Agent response:
The dataset skills_tutorial (and its contained web_analytics table) has been successfully deleted from project PROJECT_ID.
### Clean-Up Summary:
• Deleted Dataset: PROJECT_ID:skills_tutorial
• Verification Status: Confirmed deleted (Not found).
Notice how you never had to write SQL or learn the bq CLI. The agent did it all.
Cloud Run Deployment
In this step, we’ll deploy a Python application to Google Cloud Run, a fully managed compute platform that automatically scales your stateless containers. Instead of writing the code, containerizing it, and deploying it manually, we’ll let the AI agent handle the entire process.
Confirming Skill Installation
For this step, we will use the cloud-run-basics skill. Confirm it's installed:
npx skills list
Prompt-Driven Application Deployment
With the cloud-run-basics skill, the agent knows how to write application code, create optimized Dockerfiles, and deploy to Cloud Run using best practices.
1. Generating the Application Code
You prompt: Create a simple Flask web API with three endpoints: GET / (returns service info), GET /health (returns OK), and POST /analyze (accepts JSON with a text field and returns word count and character count)
Agent response:
The Flask Web API has been created in app.py and verified with tests in test_app.py.
### API Endpoints Summary
1. GET /
• Description: Returns service information and endpoints metadata.
• Response:
{
"service": "Text Analysis Web API",
"version": "1.0.0",
"status": "running",
"endpoints": [...]
}
2. GET /health
• Description: Health check endpoint.
• Response: {"status": "OK"} (HTTP 200)
3. POST /analyze
• Description: Accepts a JSON body containing a text string field and returns word count and character count.
• Sample Request:
curl -X POST http://localhost:8080/analyze \
-H "Content-Type: application/json" \
-d '{"text": "Hello world from Flask API!"}'
• Sample Response:
{
"text": "Hello world from Flask API!",
"word_count": 5,
"character_count": 27
}
──────
### How to Run locally
./.venv/bin/python3 app.py
2. Containerizing the App
You prompt: Create a Dockerfile for this Flask application
Agent response:
The Dockerfile, .dockerignore, and requirements.txt have been created.
### Dockerfile Contents:
# Use official lightweight Python image
FROM python:3.11-slim
# Prevent Python from writing .pyc files and buffer stdout/stderr
ENV PYTHONUNBUFFERED=1 \
PYTHONDONTWRITEBYTECODE=1 \
PORT=8080
# Set working directory
WORKDIR /app
# Install dependencies
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# Copy application source code
COPY app.py .
# Expose port
EXPOSE 8080
# Run the web service using Gunicorn
CMD exec gunicorn --bind 0.0.0.0:$PORT --workers 1 --threads 8 --timeout 0 app:app
──────
### Key Highlights:
• Production WSGI: Configured with gunicorn for high performance and concurrency.
• Cloud Run Compatible: Listens on dynamic $PORT (defaulting to 8080).
• Optimized Build: .dockerignore created to exclude virtual environments, cache files, and unnecessary repository metadata.
- Deploying to Cloud Run
You prompt: Deploy this application to Cloud Run in us-central1 region as a service called skills-tutorial-analyzer
Agent response:
The deployment command for skills-tutorial-analyzer to Cloud Run in us-central1 has been launched in the background. I will wait for it to complete
before proceeding.....
The Flask application has been successfully built and deployed to Cloud Run!
### Deployment Details:
• Service Name: skills-tutorial-analyzer
• Region: us-central1
• Project: PROJECT_ID
• Service URL: [https://skills-tutorial-analyzer-<PROJECT-NUMBER>.us-central1.run.app](https://skills-tutorial-analyzer-415458962931.us-central1.run.app)
──────
### Verified Endpoints:
#### 1. Service Information (GET /)
curl https://skills-tutorial-analyzer-<PROJECT-NUMBER>.us-central1.run.app/
Response:
{
"service": "Text Analysis Web API",
"version": "1.0.0",
"status": "running",
"endpoints": [...]
}
#### 2. Health Check (GET /health)
curl https://skills-tutorial-analyzer-<PROJECT-NUMBER>.us-central1.run.app/health
Response:
{
"status": "OK"
}
#### 3. Text Analysis (POST /analyze)
curl -X POST https://skills-tutorial-analyzer-<PROJECT_NUMBER>.us-central1.run.app/analyze \
-H "Content-Type: application/json" \
-d '{"text": "Hello world from deployed Cloud Run service!"}'
Response:
{
"text": "Hello world from deployed Cloud Run service!",
"word_count": 7,
"character_count": 44
}
4. Testing the Health Endpoint
You prompt: What’s the URL of my deployed service? Test it by hitting the health endpoint
Agent response:
The URL of your deployed Cloud Run service is:
🔗 https://skills-tutorial-analyzer-<PROJECT-NUMBER>.us-central1.run.app
──────
### Health Endpoint Test (GET /health)
curl -i https://skills-tutorial-analyzer-<PROJECT-NUMBER>.us-central1.run.app/health
#### Response:
HTTP/2 200
content-type: application/json
date: Thu, 23 Jul 2026 10:43:31 GMT
server: Google Frontend
{"status":"OK"}
5. Testing the Analyze Endpoint
You prompt: Send a POST request to the /analyze endpoint with the text ‘Google Cloud Skills make AI agents powerful’
Agent response:
Here is the response from sending the POST request to the /analyze endpoint:
### Request:
curl -X POST https://skills-tutorial-analyzer-<PROJECT-NUMBER>.us-central1.run.app/analyze \
-H "Content-Type: application/json" \
-d '{"text": "Google Cloud Skills make AI agents powerful"}'
──────
### Response (HTTP 200 OK):
{
"text": "Google Cloud Skills make AI agents powerful",
"word_count": 7,
"character_count": 43
}
6. Cleanup
You prompt: Delete the skills-tutorial-analyzer Cloud Run service to clean up
Agent response:
The deletion command for Cloud Run service skills-tutorial-analyzer has been launched in the background. I will wait for it to complete before
proceeding.
....
....
The Cloud Run service skills-tutorial-analyzer has been successfully deleted from region us-central1 in project PROJECT_ID.
### Clean-Up Verification:
• Service Name: skills-tutorial-analyzer
• Region: us-central1
• Status: Deleted (Verified via gcloud run services describe)
The agent wrote the code, containerized it, deployed it, and tested it — all from natural language.
To summarize
You have seen how to use Google Cloud Agent Skills now. The next part of the series will cover a few advanced skills around Architecture, Security and even writing your own Custom Skill. Stay tuned.

Top comments (0)