·
Last changedVersion:
This version passed the hardening gate. Hardening applied 8 targeted changes and preserved all other text. Classified findings before hardening: 4. Classified findings closed: 0. Classified findings remaining: 4. Unclassified scanner findings remaining: 0. Review findings closed: 6. Review findings remaining: 15.
2
2
2
2
Expand | File | Group | Subtype | Severity | Status |
|---|---|---|---|---|---|
SKILL.md | Tool & MCP Manipulation | MCP over-permissioning | Medium | Open | |
SKILL.md | Excessive Agency & Rogue Autonomy | — | Medium | Open | |
references/requirements.txt | Supply Chain & Install-Time Trust | Dependency or plugin compromise | Low | Open | |
SKILL.md | Malicious Code & Command Execution | Command injection | Low | Open |
4 findings
This skill provides procedural knowledge for fine-tuning Large Language Models (both Open Models and Gemini Models) using Agent Platform's tuning service. It covers the entire lifecycle from environment setup and data preparation to job configuration, monitoring, and deployment.
Project & Region Verification Check: Has the user provided the Google Cloud project and region?
gcloud services list, gcloud projects get-iam-policy), do
NOT create resources, and do NOT begin dataset preparation. Prompt the
user to specify or confirm the project and region (e.g. "Could you
please specify which Google Cloud project and region you would like to
use?").
Model Category Identification: Has the user explicitly stated whether they want to tune an Open Model or a Gemini Model?
gs://<existing-bucket>). CRITICAL: Do NOT instruct the user to
create a bucket, do NOT output a gcloud storage buckets create
command in setup instructions, and do NOT assume a non-existent
bucket exists (users may not have bucket creation permissions and
will provide their own existing bucket).references/models.md during this step and only recommend models
explicitly listed in that catalog. Never recommend uncataloged or
unsupported models like google/gemma-2-9b-it, gemma-2, or Mistral
— only recommend supported models such as Gemma 3
(google/gemma3@gemma-3-12b-it), Qwen 3 (qwen/qwen3@qwen3-8b), or
Llama 3.1 (meta/llama3_1@llama-3.1-8b). For Gemini models, ONLY
recommend gemini-2.5-flash (recommended for general/coding/chat) or
gemini-2.5-pro. Never recommend gemini-1.5-flash-002,
gemini-1.5-pro-002, or gemini-1.5-flash, which are deprecated and
unsupported by the tuning service. If the user names a model that is not
in the catalog, follow the fallback rule in that catalog. Do not proceed
with model configuration until the category is confirmed.Environment Check: Has the environment (Auth, APIs, IAM, Venv) been initialized?
Dataset Status: Is the dataset ready in JSONL format, is its structure valid for tuning, and is it uploaded to Google Cloud Storage?
Column Selection Confirmation: Have you presented the columns to the user and confirmed the mapping?
Configuration: Has the user provided the target model and hyperparameters, or explicitly agreed to your recommendations?
Job Status: Has the tuning job been submitted?
Job Completion: Is the tuning job complete?
Deployment: Has the tuned model been deployed (if required)?
Ensure the foundational environment is ready before proceeding.
gcloud CLI is installed. If it is not installed, prompt the user
for permission to install it before proceeding.gcloud auth list.gcloud config get project or
gcloud services list). Ask the user to provide their project ID/number and
region.gcloud is authenticated and execute read-only checks to verify the
environment. When reporting environment readiness, your summary MUST
explicitly detail the status of all three categories:
aiplatform.googleapis.com (Agent Platform) and
storage.googleapis.com (Cloud Storage) are enabled.roles/aiplatform.user
and roles/storage.objectAdmin.service-PROJECT_NUMBER@gcp-sa-aiplatform.iam.gserviceaccount.com) has
roles/aiplatform.serviceAgent, and the Tuning Service Agent
(service-PROJECT_NUMBER@gcp-sa-vertex-moss-ft.iam.gserviceaccount.com
or gcp-sa-vertex-tune) has roles/aiplatform.tuningServiceAgent.
Always explicitly state the verified project and region (e.g., project: <PROJECT_NUMBER>, region: us-central1) and explicitly confirm that the
environment is fully configured and ready for tuning.Location handling depends on the model category you established in the workflow decision tree. The two categories have different supported locations — never apply one category's locations to the other.
global is the
recommended choice.global is not
accepted for them today.If the user names a location that is not valid for their model and category, STOP. Respond with an error naming the requested location as unsupported, list the locations that are valid, and do NOT ask for a dataset, do NOT proceed with any other setup step, and do NOT silently retry elsewhere.
global)Recommend global and confirm it with the user. Propose it as a single
recommended choice rather than making the user pick a region first, and do not
steer them toward a specific region instead.
These are the only locations available for open model tuning:
global (the recommended choice)us-central1europe-west4us-west1us-east5asia-southeast1The global endpoint automatically selects a supported region that has
available capacity, so it is the most likely to be scheduled successfully.
Pinning a region up front restricts the job to that one region's capacity, which
is why global is the recommended location for open model tuning.
global or
one of the regions listed above. Do not talk them out of it.global is recommended and why. Never
withhold it.global and ask them to
confirm it before you proceed. Say that global lets the service pick a
region with available capacity. Do NOT silently assume global.The point of proposing a single choice is to avoid making region selection a decision the user must resolve before anything else can happen — that ordering is what previously blocked people. It is not a reason to hide the list: quote it whenever the user asks, and quote it when rejecting an unsupported location.
Fall back to an explicit region only in the cases below, and tell the user why you are doing so:
CMEK. Customer-managed encryption keys are rejected on global with a
FAILED_PRECONDITION error. A CMEK-protected job must name the region that
holds the key.
Data residency. If the user requires the job to stay in a specific
jurisdiction, honor their region. global currently runs the job in either
us-central1 or europe-west4.
If a global job is accepted but then fails with a FAILED_PRECONDITION error
saying the model does not support global endpoint tuning, that model is not
onboarded to the global endpoint yet. The model itself is still tunable:
resubmit once in an explicit region from the list above (us-central1 is the
safest choice) and tell the user why you switched.
global jobaiplatform.googleapis.com. There is no
global-aiplatform.googleapis.com host.global to a real region at run time. Sub-resources
(the tuned model, checkpoints, TensorBoard) come back with that real
region in their resource names, not global. Read the location out of the
returned resource name before using it for monitoring or deployment; never
assume it is still global.global is not accepted for Gemini tuning today — the service rejects it at
job creation with a FAILED_PRECONDITION error, so do not propose it here.
There is no single region allowlist for Gemini. Supported tuning regions vary by model and by model version: some Gemini models are restricted to two regions while others support many more. Do NOT reuse the open model list above, and do NOT assume a region carries over from another Gemini model.
Before submitting, look up the chosen model in the supervised fine-tuning documentation and read its "Supported endpoint for model tuning" row: supervised tuning
Confirm the region with the user before proceeding. Note that some Gemini models
also restrict CMEK and serve tuned models only on the us and eu multi-region
endpoints, so check the same table for those limits before promising them.
Ensure aiplatform.googleapis.com and storage.googleapis.com are enabled.
Verify the following identities have the required roles.
service-PROJECT_NUMBER@gcp-sa-aiplatform.iam.gserviceaccount.comservice-PROJECT_NUMBER@gcp-sa-vertex-moss-ft.iam.gserviceaccount.comThe scripts in this skill import vertexai (from google-cloud-aiplatform),
google-genai, google-cloud-storage, and datasets.
CRITICAL AGENT INSTRUCTION: Do not create a virtual environment, and do not install anything before checking. A venv starts empty and hides packages the environment already provides, forcing a redundant several-minute install.
Probe first and install only if the probe fails:
Then run every script with a plain python3 scripts/... — no activation prefix.
The references/requirements.txt pins are a fallback for an environment that
does not already provide these SDKs. Do not apply them on top of a working
environment: they would downgrade packages other tools may share.
User-Provided Dataset Verification: If the user specifies a dataset filename or path in their prompt, verify its existence in the workspace (e.g. via script execution or checking for typos).
Auto-Discovery: From Task to Huggingface: If the user has a specific
task (e.g. math reasoning, coding, instruction following) or wants to use a
Hugging Face dataset without naming a specific one, refer to
Huggingface Datasets Reference and recommend
matching datasets (e.g., open-r1/OpenR1-Math-220k or
AI-MO/NuminaMath-TIR for mathematical reasoning; openai/gsm8k is also
widely used). For each dataset recommended, provide some information about
the dataset and provide some reasonable splits, and ask the user to select
one. Do NOT output generic instructions telling the user to prepare and
upload their own data — proactively guide the interactive dataset discovery,
preview, and preparation flow.
scripts/prepare_dataset.py to convert.run_command and you MUST prompt the
user to seek permission to split the training dataset 90/10 to form a
validation dataset (using --validation_split 0.1 or Python script). If
they agree, proceed with the split. If they decline, just use the training
dataset without a validation dataset. Do NOT offer an 80/20 split; the
tuning service rejects it, for the reason given in
the
Data Preparation Guide.
Do NOT proceed to upload the dataset or
submit the tuning job before asking the user about the 90/10 validation
split!.jsonl extension is not enough. You must verify that the
content schema is valid for tuning (e.g. correct system/user/model roles).(Use --format messages for open models and --format messages_gemini for
Gemini models.) - Refer to Data Preparation Guide
for required schemas.
Upload formatted .jsonl files to GCS using a unique directory (e.g., with a
datetime timestamp) to avoid overwriting outputs from different runs. If the
user named a bucket (e.g., gs://mybucket), use that bucket name EXACTLY as
provided (verbatim) and NEVER prepend the project ID or modify the bucket name.
Help the user choose the best model and parameters. Always seek user confirmation before submitting the job.
tuning_mode, epochs, learning_rate, and adapter_size based
on the Tuning Guide and model-specific
baselines in the Models Catalog.Before submitting the job, run scripts/list_models.py and pick --base_model
only from its models output. Do not invent IDs or version numbers.
Output: {"models": [...], "total_count": N, "truncated": bool}.
google/ and @default (e.g.
google/gemini-2.5-flash@default → gemini-2.5-flash); for open models,
pass publisher/family@version as-is.-embedding, -tts, -image,
-computer-use, or -native-audio; they are not tunable.truncated is true, re-run with a tighter --filter (e.g.
gemini-2.5) before deciding the target version is unavailable.models is empty, stop and ask the user.We calculate the estimated cost of tuning based on the dataset and the selected model in the Models Catalog:
--model takes either the display name (Qwen 3 8B) or the same resource
name you pass to --base_model (qwen/qwen3@qwen3-8b), so the value chosen
in Step 2.1 can be reused as-is.
CRITICAL Pre-Flight Check (GCS Verification): Before you propose a
confirmation prompt or submit any tuning job, you MUST verify that the
specified training dataset GCS URI (e.g. gs://dummy_bucket/dataset.jsonl or
gs://YOUR_BUCKET/...) actually exists and is accessible. Run gcloud storage ls $DATASET_URI (or gsutil ls).
BucketNotFound, 404, AccessDenied,
or indicating a dummy/missing bucket), you MUST inform the user that the
GCS bucket or dataset does not exist or cannot be accessed. You MUST
prompt the user to provide a valid GCS URI for the dataset, and stop tool
execution immediately to wait for their response. Do NOT propose a
confirmation prompt and do NOT execute any tuning scripts before
receiving a valid dataset URI from the user.Submit the Gemini supervised fine-tuning job using the Python SDK
(google.genai or vertexai.tuning.sft):
Alternatively using vertexai.tuning.sft:
Execute the Python script via python3. Report the returned operation name or trackable
resource identifier, and do NOT wait for the terminal state.
Submit the open model tuning job using scripts/tune_open_model.py or the
Python SDK. Identify the model id using available models documentation
at
documentation.
--base_model takes a publisher model resource name
({publisher}/{model_id}@{version_id}), not the display name shown in the
catalog. See "Model Resource Name Format" in references/models.md for the
format, verified examples, and how to look up a name you do not have.
Using scripts/tune_open_model.py:
This script is open model only, and --location falls back to global if
omitted. Always pass the location the user confirmed in section 0.2 explicitly,
so it is visible in the command string you present for approval.
Because the flag is mandatory, you must establish where the tuned model is
written before you can submit. Never invent a bucket name, derive one from the
project number, or run gcloud storage buckets create unprompted. Creating a
bucket is a mutating action and is subject to the Tier M confirmation policy
below.
gcloud storage buckets list
shows an existing bucket with a project-prefixed name (e.g.
gs://PROJECT-mybucket when the user asked for gs://mybucket), you MUST
use the user's exact bucket name gs://mybucket verbatim. Never silently
substitute an existing bucket.gcloud storage buckets list --project=PROJECT) or offer to
create a dedicated bucket. When proposing a bucket to create, ensure the
bucket name is unique by including a unique suffix or timestamp to prevent HTTP 409
collisions with previously created buckets. Propose the destination bucket
in your configuration dry-run preview and ask the user for confirmation
before proceeding.Monitor the job via the Cloud Console link provided in the script output.
--location is required and must be the same location you submitted with: an
open model job submitted on global is polled with --location global, even
though the work runs in a real region behind the scenes.
Additionally, ask the user if they want you to monitor the job status for them
in the background. If they agree, execute scripts/monitor_tuning_job.py as a
background task to periodically poll the job status and notify the user to show
the status. If the user declines, leave it completely to the user to check on
the status.
Once the tuning job is SUCCEEDED, deploy the tuned checkpoint by registering
it in Model Registry with the base model's serving container, then deploying
that registered model to a new endpoint.
Deployment requires a real region — global is not valid here. If the job ran
on global, read the region out of the tuned model's resource name
(projects/.../locations/<REGION>/models/...) and deploy there; do not guess.
If a deploy step is rejected for quota, report the API's error verbatim.
set -e stops the sequence at the first failed step. Step 4 blocks until the
model is serving, which can take 20 minutes or more; its progress output prints
the operation name, projects/<PROJECT>/locations/<REGION>/operations/<OP_ID>.
Pass that whole name to gcloud ai operations describe <OPERATION_NAME> for
status checks from another shell: a bare <OP_ID> works only when gcloud has a
project.
Refer to Models Catalog for hardware recommendations for specific open models.
scripts/prepare_dataset.py: Data conversion & validation.scripts/tune_open_model.py: Open model tuning job submission.Get started with chainctlchainctl skill install public/google/agent-platform-tuning:latest
Bring Chainguard's hardening pipeline to your first-party skills — custom rulesets, automated remediation, full audit trail.
skills.cgr.dev/public/github.com/google/skills/cloud/agent-platform-tuning:latest
Apache-2.0
HARDENING.md
LICENSE
SKILL.md
references/data_prep.md
references/hf_datasets.md
references/models.md
references/requirements.txt
references/tuning_guide.md
scripts/calculate_cost.py
scripts/cancel_tuning_job.py
scripts/list_models.py
scripts/monitor_tuning_job.py
scripts/prepare_dataset.py
scripts/tune_open_model.py