Agent Platform Skill Registry
GoogleOfficialPublished by Google
- Skill
- Meta (authoring, orchestration, planning, memory)
- Agent tooling
- Apache-2.0
- Low risk
- Has scripts
AutoGineer summary
Written by AutoGineer from the skill’s own files, not by the author
The agent-platform-skill-registry skill provides a comprehensive interface for interacting with the Gemini Enterprise Agent Platform's skill registry. It enables developers and agents to perform lifecycle management tasks such as creating, updating, and deleting skills, as well as searching for existing capabilities. Additionally, it includes utility functions for scaffolding new skills with standardized directory structures and documentation, ensuring consistency across agent development workflows.
What it does
- Search, list, and inspect revision histories of available agent skills.
- Manage the full lifecycle of skills including uploading, updating, and deletion.
- Monitor the status of long-running operations for state changes.
- Automate the initial scaffolding of new agent skills with standardized structures.
- Validate the local environment to ensure prerequisites are met before operations.
- Provide standardized attribution for CLI and API interactions.
When to use it
- When you need to discover existing skills to integrate into an agent.
- When you are developing a new skill and need to scaffold its structure.
- When you need to register or update a skill in the Gemini Enterprise Agent Platform.
- When you need to monitor the progress of long-running registry operations.
Advantages
- Promotes consistency through standardized directory structures and documentation.
- Simplifies the discovery of existing capabilities within the platform.
- Provides built-in environment validation to prevent execution errors.
- Includes clear guidelines for usage attribution and API interaction.
Usage examples
- “Search for skills related to data processing in the registry.”
- The agent queries the registry and returns a list of relevant skills matching the 'data processing' query.
- “Scaffold a new skill for my agent called 'weather-fetcher'.”
- The agent creates the standard directory structure and a draft SKILL.md file for the new skill.
Install
Download the skill as a ZIP:
https://autogineer.com/agent-skills/google/agent-platform-skill-registry/downloadUnzip it into the cross-client skills folder of your project:
mkdir -p .agents/skills && unzip agent-platform-skill-registry.zip -d .agents/skills
Documentation by Google
Skill Registry
This skill provides instructions for interacting with the Skill Registry on the Gemini Enterprise Agent Platform.
Attribution
MUST READ: Before executing any gcloud, REST API, or MCP command, you
MUST read Usage Attribution. For commands executed
directly in the terminal (never in generated scripts, Terraform, or user code),
prefix gcloud with
CLOUDSDK_METRICS_REQUEST_ATTRIBUTION="agent-skills/1.0 (skill:agent-platform-skill-registry)"
and append
agent-skills/1.0 (skill:agent-platform-skill-registry)
to User-Agent headers.
Core Capabilities
Skill Discovery - Query the registry to easily search, list, get specific skills, and inspect revision histories.
Skill Lifecycle Management - Upload, update, or permanently delete skills.
Operation Monitoring - Utility to check the completion status of long-running state changes (LROs).
Generate Skill - Automate the initial scaffolding of new agent skills locally.
Core Directives
Mandatory Validation: ALWAYS execute the environment validation check before performing any operations.
Before any operation, you must validate the core environment.
# Execute the validation script python3 scripts/validate_env.py
Prerequisites & Authentication
Library & Authentication
Ensure you have the latest Google Cloud credentials and libraries installed.
# Install required libraries
pip install google-auth requests
# Authenticate with Google Cloud
gcloud auth application-default loginEnvironment Variables
The following variables are required for operations:
GCP_PROJECT_ID: Your Google Cloud Project ID.GCP_LOCATION: The region (e.g.,us-central1).
Quickstart
Quickly search for available skills in the registry:
python3 scripts/skill_registry_ops.py search \
--query "test skill" \
--top-k 5Operations
Skill Discovery: query-skills.md
Skill Lifecycle: manage-skills.md
Monitor Operations: monitor-operations.md
Generate Skill: generate-skill.md
Files
- ATTRIBUTION.mdAdded by AutoGineer876 B
- LICENSELicence file added by AutoGineer11.1 KiB
- SKILL.md2.7 KiB
- references/attribution.md1.9 KiB
- references/generate-skill.md2.6 KiB
- references/manage-skills.md2.4 KiB
- references/monitor-operations.md619 B
- references/query-skills.md1.5 KiB
- scripts/requirements.txt83 B
- scripts/skill_registry_ops.pyScript10.8 KiB
- scripts/validate_env.pyScript454 B
scripts/skill_registry_ops.py
"""A script to perform operations on the Skill Registry."""
import argparse
import base64
import io
import json
import os
import sys
import urllib.parse
import zipfile
import google.auth
from google.auth.transport.requests import Request
import requests
def get_access_token():
credentials, _ = google.auth.default()
credentials.refresh(Request())
return credentials.token
def get_endpoint(region):
return f"{region}-aiplatform.googleapis.com"
def upload(args):
"""Uploads a new skill in the Skill Registry.
Args:
args: The command line arguments.
"""
token = get_access_token()
endpoint = get_endpoint(args.location)
url = f"https://{endpoint}/v1beta1/projects/{args.project}/locations/{args.location}/skills?skillId={args.skill_id}"
headers = {
"Authorization": f"Bearer {token}",
"Content-Type": "application/json",
}
if args.zip_file:
with open(args.zip_file, "rb") as f:
zip_bytes = f.read()
elif args.folder:
zip_buffer = io.BytesIO()
with zipfile.ZipFile(zip_buffer, "w", zipfile.ZIP_DEFLATED) as zip_file:
for root, _, files in os.walk(args.folder):
for file in files:
file_path = os.path.join(root, file)
arcname = os.path.relpath(file_path, args.folder)
zip_file.write(file_path, arcname)
zip_bytes = zip_buffer.getvalue()
else:
raise ValueError("Must provide either --zip-file or --folder")
zipped_filesystem = base64.b64encode(zip_bytes).decode("utf-8")
payload = {
"displayName": args.display_name,
"description": args.description,
"zippedFilesystem": zipped_filesystem,
}
print(f"Uploading skill {args.skill_id} at {endpoint}...")
response = requests.post(url, headers=headers, json=payload)
if response.status_code >= 400:
print(f"Error: {response.status_code} - {response.text}")
sys.exit(1)
print("Response:")
print(json.dumps(response.json(), indent=2))
def search(args):
"""Searches for skills in the Skill Registry."""
token = get_access_token()
endpoint = get_endpoint(args.location)
query_encoded = urllib.parse.quote(args.query)
url = f"https://{endpoint}/v1beta1/projects/{args.project}/locations/{args.location}/skills:retrieve?query={query_encoded}&topK={args.top_k}"
headers = {
"Authorization": f"Bearer {token}",
"Content-Type": "application/json",
}
print(f"Searching skills at {endpoint} with query '{args.query}'...")
response = requests.get(url, headers=headers)
if response.status_code >= 400:
print(f"Error: {response.status_code} - {response.text}")
sys.exit(1)
print("Response:")
print(json.dumps(response.json(), indent=2))
def get_skill(args):
"""Gets a skill from the Skill Registry."""
token = get_access_token()
endpoint = get_endpoint(args.location)
url = f"https://{endpoint}/v1beta1/projects/{args.project}/locations/{args.location}/skills/{args.skill_id}"
headers = {
"Authorization": f"Bearer {token}",
}
print(f"Getting skill {args.skill_id} at {endpoint}...")
response = requests.get(url, headers=headers)
if response.status_code >= 400:
print(f"Error: {response.status_code} - {response.text}")
sys.exit(1)
print("Response:")
print(json.dumps(response.json(), indent=2))
def list_skills(args):
"""Lists skills in the Skill Registry."""
token = get_access_token()
endpoint = get_endpoint(args.location)
url = f"https://{endpoint}/v1beta1/projects/{args.project}/locations/{args.location}/skills"
headers = {
"Authorization": f"Bearer {token}",
}
print(f"Listing skills at {endpoint}...")
response = requests.get(url, headers=headers)
if response.status_code >= 400:
print(f"Error: {response.status_code} - {response.text}")
sys.exit(1)
print("Response:")
print(json.dumps(response.json(), indent=2))
def delete_skill(args):
"""Deletes a skill from the Skill Registry."""
token = get_access_token()
endpoint = get_endpoint(args.location)
url = f"https://{endpoint}/v1beta1/projects/{args.project}/locations/{args.location}/skills/{args.skill_id}"
headers = {
"Authorization": f"Bearer {token}",
}
print(f"Deleting skill {args.skill_id} at {endpoint}...")
response = requests.delete(url, headers=headers)
if response.status_code >= 400:
print(f"Error: {response.status_code} - {response.text}")
sys.exit(1)
print("Response:")
print(json.dumps(response.json(), indent=2))
def update_skill(args):
"""Updates an existing skill in the Skill Registry."""
token = get_access_token()
endpoint = get_endpoint(args.location)
update_mask_parts = []
payload = {}
if args.display_name:
update_mask_parts.append("displayName")
payload["displayName"] = args.display_name
if args.description:
update_mask_parts.append("description")
payload["description"] = args.description
if args.zip_file or args.folder:
if args.zip_file:
with open(args.zip_file, "rb") as f:
zip_bytes = f.read()
elif args.folder:
zip_buffer = io.BytesIO()
with zipfile.ZipFile(zip_buffer, "w", zipfile.ZIP_DEFLATED) as zip_file:
for root, _, files in os.walk(args.folder):
for file in files:
file_path = os.path.join(root, file)
arcname = os.path.relpath(file_path, args.folder)
zip_file.write(file_path, arcname)
zip_bytes = zip_buffer.getvalue()
zipped_filesystem = base64.b64encode(zip_bytes).decode("utf-8")
update_mask_parts.append("zippedFilesystem")
payload["zippedFilesystem"] = zipped_filesystem
if not update_mask_parts:
print(
"Error: must provide at least one field to update (--display-name,"
" --description, --zip-file, --folder)"
)
sys.exit(1)
update_mask = ",".join(update_mask_parts)
url = f"https://{endpoint}/v1beta1/projects/{args.project}/locations/{args.location}/skills/{args.skill_id}?updateMask={update_mask}"
headers = {
"Authorization": f"Bearer {token}",
"Content-Type": "application/json",
}
print(f"Updating skill {args.skill_id} at {endpoint}...")
response = requests.patch(url, headers=headers, json=payload)
if response.status_code >= 400:
print(f"Error: {response.status_code} - {response.text}")
sys.exit(1)
print("Response:")
print(json.dumps(response.json(), indent=2))
def list_skill_revision(args):
"""Lists revisions of a skill in the Skill Registry."""
token = get_access_token()
endpoint = get_endpoint(args.location)
url = f"https://{endpoint}/v1beta1/projects/{args.project}/locations/{args.location}/skills/{args.skill_id}/revisions"
headers = {
"Authorization": f"Bearer {token}",
}
print(f"Listing revisions for skill {args.skill_id} at {endpoint}...")
response = requests.get(url, headers=headers)
if response.status_code >= 400:
print(f"Error: {response.status_code} - {response.text}")
sys.exit(1)
print("Response:")
print(json.dumps(response.json(), indent=2))
def get_skill_revision(args):
"""Gets a specific revision of a skill from the Skill Registry."""
token = get_access_token()
endpoint = get_endpoint(args.location)
url = f"https://{endpoint}/v1beta1/projects/{args.project}/locations/{args.location}/skills/{args.skill_id}/revisions/{args.revision_id}"
headers = {
"Authorization": f"Bearer {token}",
}
print(
f"Getting skill {args.skill_id} revision {args.revision_id} at"
f" {endpoint}..."
)
response = requests.get(url, headers=headers)
if response.status_code >= 400:
print(f"Error: {response.status_code} - {response.text}")
sys.exit(1)
print("Response:")
print(json.dumps(response.json(), indent=2))
def monitor(args):
"""Monitors the status of a long-running operation."""
token = get_access_token()
endpoint = get_endpoint(args.location)
op_id = args.operation_id.lstrip("/")
url = f"https://{endpoint}/v1beta1/{op_id}"
headers = {
"Authorization": f"Bearer {token}",
}
print(f"Monitoring operation {args.operation_id} at {endpoint}...")
response = requests.get(url, headers=headers)
if response.status_code >= 400:
print(f"Error: {response.status_code} - {response.text}")
sys.exit(1)
print("Response:")
print(json.dumps(response.json(), indent=2))
def main():
parser = argparse.ArgumentParser(
description="Skill Registry Operations Utility"
)
parser.add_argument("--project", default=os.environ.get("GCP_PROJECT_ID"))
parser.add_argument("--location", default=os.environ.get("GCP_LOCATION"))
subparsers = parser.add_subparsers(dest="action", required=True)
upload_parser = subparsers.add_parser("upload")
upload_parser.add_argument("--skill-id", required=True)
upload_parser.add_argument("--display-name", required=True)
upload_parser.add_argument("--description", required=True)
group = upload_parser.add_mutually_exclusive_group(required=True)
group.add_argument("--zip-file")
group.add_argument("--folder")
search_parser = subparsers.add_parser("search")
search_parser.add_argument("--query", required=True)
search_parser.add_argument("--top-k", type=int, default=5)
get_parser = subparsers.add_parser("get")
get_parser.add_argument("--skill-id", required=True)
subparsers.add_parser("list")
delete_parser = subparsers.add_parser("delete")
delete_parser.add_argument("--skill-id", required=True)
update_parser = subparsers.add_parser("update")
update_parser.add_argument("--skill-id", required=True)
update_parser.add_argument("--display-name", required=False)
update_parser.add_argument("--description", required=False)
update_group = update_parser.add_mutually_exclusive_group(required=False)
update_group.add_argument("--zip-file")
update_group.add_argument("--folder")
list_rev_parser = subparsers.add_parser("list-revision")
list_rev_parser.add_argument("--skill-id", required=True)
get_rev_parser = subparsers.add_parser("get-revision")
get_rev_parser.add_argument("--skill-id", required=True)
get_rev_parser.add_argument("--revision-id", required=True)
monitor_parser = subparsers.add_parser("monitor")
monitor_parser.add_argument("--operation-id", required=True)
args = parser.parse_args()
missing = []
if not args.project:
missing.append("GCP_PROJECT_ID")
if not args.location:
missing.append("GCP_LOCATION")
if missing:
print(
f"ERROR: Missing required environment variables: {', '.join(missing)}"
)
sys.exit(1)
if args.action == "upload":
upload(args)
elif args.action == "search":
search(args)
elif args.action == "get":
get_skill(args)
elif args.action == "list":
list_skills(args)
elif args.action == "delete":
delete_skill(args)
elif args.action == "update":
update_skill(args)
elif args.action == "list-revision":
list_skill_revision(args)
elif args.action == "get-revision":
get_skill_revision(args)
elif args.action == "monitor":
monitor(args)
if __name__ == "__main__":
main()
Requirements and compatibility
Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta
“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.
Needs: Needs a command-line tool, Needs Python
Security
What our scanner noticed· Low risk
- Instructions that use the network
- Scripts that your agent may run
This skill includes scripts that your agent may run. Read them before you use it.
A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.
Attribution and licence
- Published by
- Publisher
- Google (Official)
- Source
- google/skills · skills/cloud/agent-platform-skill-registry · commit 2194d3b
- Licence
- Apache License 2.0 (redistribution allowed)
- LICENSE (added by AutoGineer from LICENSE)
- ATTRIBUTION.md (written by AutoGineer)
- Synced
AutoGineer is not affiliated with or endorsed by Google or Google.
Download ZIP
The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download agent-platform-skill-registry.zip