Calling Gemini on Google Cloud is an authenticated API call from your code. No API key in the code: use Application Default Credentials and IAM.
flowchart LR APP["Cloud Run service<br/>runs as chat-sa"] -- "ADC token" --> API["aiplatform.googleapis.com<br/>location global"] API --> MA["Model Armor<br/>prompt injection, sensitive data"] MA --> GEM["Gemini model"] GEM --> SAFE["Safety filters"] SAFE --> APP %% step APP: The service runs as chat-sa, which has the Vertex AI User role; the SDK gets tokens automatically from the metadata server. %% step API: Requests go to the Agent Platform / Vertex AI API, here on the global endpoint. %% step MA: Optionally, Model Armor screens prompts for prompt injection, jailbreaks and sensitive data before they reach the model. %% step GEM: The model generates a response; you pay for input and output tokens. %% step SAFE: Built-in safety filters can block harmful content in the response by category and threshold.
Authentication and roles
- Grant the calling identity Vertex AI User (
roles/aiplatform.user) on the project. - On Cloud Run, GKE or a VM, the attached service account is used automatically; locally,
gcloud auth application-default login. - Avoid API keys in code; if a key is unavoidable for a prototype, restrict it and keep it in Secret Manager.
SDK and REST
# pip install google-genai
# env: GOOGLE_GENAI_USE_VERTEXAI=True GOOGLE_CLOUD_PROJECT=dl-ai-dev GOOGLE_CLOUD_LOCATION=global
from google import genai
client = genai.Client()
resp = client.models.generate_content(
model="gemini-3.5-flash", # check the current model list for IDs
contents="Summarise this customer complaint in one sentence: …")
print(resp.text)
curl -X POST -H "Authorization: Bearer $(gcloud auth print-access-token)" -H "Content-Type: application/json" https://aiplatform.googleapis.com/v1/projects/dl-ai-dev/locations/global/publishers/google/models/gemini-3.5-flash:generateContent -d '{"contents":[{"role":"user","parts":[{"text":"Hello"}]}]}'
Tokens, cost and quotas
| Topic | What to know |
|---|---|
| Pricing | Per million input and output tokens; Flash-Lite < Flash < Pro |
| Context caching | Reuse a long prompt prefix at a lower price |
| Batch prediction | Large offline jobs at about half the online price |
| Quotas | Many Gemini models use dynamic shared quota: no fixed per-project limit, but HTTP 429 when capacity is busy; retry with exponential backoff |
| Provisioned Throughput | Reserve capacity for predictable latency and volume |
Set max output tokens, keep prompts short, and log token counts (usage_metadata) to watch cost.
Safety
- Safety settings per request: harm categories (harassment, hate speech, sexually explicit, dangerous content) with block thresholds.
- Model Armor screens prompts and responses for prompt injection, jailbreak attempts, sensitive data (via Sensitive Data Protection) and malicious URLs, across models.
- Use system instructions to set the assistant’s role and limits; never trust user input to override them.
| Command | Meaning |
|---|---|
gcloud projects add-iam-policy-binding dl-ai-dev --member=serviceAccount:chat-sa@dl-ai-dev.iam.gserviceaccount.com --role=roles/aiplatform.user |
Allow the app to call models |
gcloud auth print-access-token |
Token for a quick curl test |
Traps: a 429 is usually capacity, not a bug, so add backoff; long chat histories are re-sent and billed as input tokens on every turn; outputs can be wrong or unsafe, so validate them before acting on them.