agentleFS
drinkspillerdrinkspiller/skills/gemini-api/SKILL.md

gemini-api

Skill1 starsChanged 5 days agoUnlicenseView on GitHub

Practical guide and zero-dependency recipes for calling Google's Gemini API directly (HTTP/REST, Python urllib, curl). Use when generating text, structured JSON, running batch LLM calls, configuring models, or setting up GEMINI_API_KEY without needing skill-opt.

  • Reads credentials
  • Sends data out

9 other projects use a version of this.

Adopted by

Most recently taken up by

The file

We split this skill into the rules it gives an agent

11 rules. 0 are common, 4 are distinctive, and 7 are very specific to this project.

  • 0

    Common

    Most of the 9 edited versions we read keep these.

  • 4

    Distinctive

    This author's own choices. Worth a look.

  • 7

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  • could be automatic: a setting could enforce it
  1. Very specific:

    All requests authenticate via an API key passed in the query parameter ?key=${GEMINI_API_KEY} or header x-goog-api-key.

    line 15
  2. Distinctive:

    Always prefer these canonical aliases for general text and reasoning tasks.

    line 51
  3. Distinctive:

    Use these when pinning to specific generation architectures or preview features:

    line 61
  4. Distinctive:

    When automating API calls, design model selection hierarchically:

    line 81
  5. Very specific:

    Use this production-grade, self-contained implementation without needing external packages (requests, google-generativeai):

    line 90
  6. Very specific:

    Run multiple prompts in parallel using concurrent.futures:

    line 195
  7. Distinctive:

    Test an API key and connectivity from the shell in one line:

    line 222
  8. Very specific:

    System Instructions Placement: Never put system prompts in contents.

    line 236
  9. Very specific:

    Always place them in the dedicated top-level system_instruction: {"parts": [{"text": "..."}]} block.

    line 237
  10. Very specific:

    Key Security: Never commit raw API keys to Git, Fig, Piper, or review CLs.

    line 239
  11. Very specific:

    Candidate Parsing: Always guard access: res.get("candidates", [])[0].get("content", {}).get("parts", [])[0].get("text", "").

    line 241

“Common” is measured: kept by at least 6 in 10 of the 9 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Calling the Gemini API

This skill provides direct, zero-dependency recipes and reference patterns for calling Google's Gemini API across Python and the command line.


1. Authentication & Environment

All requests authenticate via an API key passed in the query parameter ?key=${GEMINI_API_KEY} or header x-goog-api-key.

Environment Setup

# Check if key is present
echo "$GEMINI_API_KEY"

# If not set, export in ~/.bashrc or current shell
export GEMINI_API_KEY="AIzaSy..."

In Python:

import os
import sys

api_key = os.environ.get("GEMINI_API_KEY", "")
if not api_key:
    sys.exit("ERROR: GEMINI_API_KEY environment variable is not set.")

2. Models & Capabilities

Endpoint template:

https://generativelanguage.googleapis.com/v1beta/models/{MODEL}:generateContent?key={API_KEY}

Preferred First Choices (Auto-Updating Pointers)

Always prefer these canonical aliases for general text and reasoning tasks. They automatically resolve to the latest stable production model snapshots:

Model AliasPurposeLatency / Throughput
gemini-pro-latestComplex reasoning, multi-step refactoring, architecture critique, system analysisHighest quality, medium latency
gemini-flash-latestGeneral text generation, code transformation, balanced synthesisFast, balanced quality
gemini-flash-lite-latestHigh-volume batch evaluation, rapid classification, scoring, triageLowest latency, highest QPS

Alternative & Fixed Version Models (Alts)

Use these when pinning to specific generation architectures or preview features:

ModelClassificationDescription
gemini-3.8-flashLatest Flash generationAdvanced speed-optimized model with expanded context reasoning
gemini-3.7-flashStable Flash generationHigh-performance reasoning with low latency
gemini-3.6-flashWorkhorse FlashProven balanced reasoning and code generation
gemini-3.1-pro-previewDeep Pro previewFrontier reasoning for architectural design and complex debugging

Specialized Image Models (Image Generation & Edits Only)

These models use the standard :generateContent endpoint but return image payloads inside candidates[0].content.parts[].inlineData (image/png or image/jpeg) rather than text:

ModelTaskEndpoint / Notes
gemini-3.1-flash-imageRapid image generation & editsFast image synthesis via :generateContent
gemini-3-pro-imageHigh-fidelity image generationMulti-turn visual refinement and detailed asset synthesis

Dynamic Model Fallback Strategy

When automating API calls, design model selection hierarchically:

  1. Try gemini-flash-latest (or gemini-flash-lite-latest for batch jobs).
  2. Fallback to gemini-pro-latest.
  3. Fallback to pinned snapshots (gemini-3.8-flash, gemini-3.7-flash, gemini-3.1-pro-preview).

3. Zero-Dependency Python Helper (Standard Library)

Use this production-grade, self-contained implementation without needing external packages (requests, google-generativeai):

import json
import os
import time
import urllib.error
import urllib.request
from typing import Any, Dict, List, Optional

def call_gemini(
    prompt: str,
    system_instruction: Optional[str] = None,
    model: str = "gemini-flash-latest",
    fallback_models: Optional[List[str]] = None,
    temperature: float = 0.2,
    max_output_tokens: Optional[int] = None,
    json_mode: bool = False,
    api_key: Optional[str] = None,
    max_retries: int = 3
) -> str:
    """Invokes Gemini API with model fallback and exponential backoff."""
    key = api_key or os.environ.get("GEMINI_API_KEY", "")
    if not key:
        raise ValueError("GEMINI_API_KEY not configured in environment.")

    candidate_models = [model] + (fallback_models or [
        "gemini-pro-latest",
        "gemini-flash-lite-latest",
        "gemini-3.8-flash",
        "gemini-3.7-flash",
        "gemini-3.1-pro-preview"
    ])

    # Payload Construction
    payload: Dict[str, Any] = {
        "contents": [{"parts": [{"text": prompt}]}],
        "generationConfig": {
            "temperature": temperature,
        }
    }

    if system_instruction:
        payload["system_instruction"] = {
            "parts": [{"text": system_instruction}]
        }

    if max_output_tokens:
        payload["generationConfig"]["maxOutputTokens"] = max_output_tokens

    if json_mode:
        payload["generationConfig"]["responseMimeType"] = "application/json"

    data_bytes = json.dumps(payload).encode("utf-8")

    for current_model in candidate_models:
        url = f"https://generativelanguage.googleapis.com/v1beta/models/{current_model}:generateContent?key={key}"

        for attempt in range(1, max_retries + 1):
            req = urllib.request.Request(
                url,
                data=data_bytes,
                headers={"Content-Type": "application/json"}
            )
            try:
                with urllib.request.urlopen(req, timeout=60) as resp:
                    res = json.loads(resp.read().decode("utf-8"))
                    cands = res.get("candidates", [])
                    if cands and "content" in cands[0]:
                        parts = cands[0]["content"].get("parts", [])
                        if parts and "text" in parts[0]:
                            return parts[0]["text"].strip()
                    return ""
            except urllib.error.HTTPError as e:
                # 404 or 503: model unavailable -> try fallback model
                if e.code in (404, 503):
                    break
                # 429: rate limited -> backoff
                time.sleep(2 ** attempt)
            except Exception:
                time.sleep(2 ** attempt)

    return ""

4. Common Recipes

A. Structured JSON Extraction

schema_prompt = "Extract entities and status from: 'Host db-prod-01 CPU peaked at 98% and failed health check.'"
response_json = call_gemini(
    prompt=schema_prompt,
    system_instruction="You are an automated triage parser. Output valid JSON matching: {'host': str, 'metric': str, 'status': str}.",
    json_mode=True
)
data = json.loads(response_json)
print(data["host"], data["status"])

B. High-Throughput Concurrent Batch Calls

Run multiple prompts in parallel using concurrent.futures:

import concurrent.futures

prompts = [
    ("Prompt 1", "Explain Paxos"),
    ("Prompt 2", "Explain Raft"),
    ("Prompt 3", "Explain 2PC")
]

def worker(item):
    label, text = item
    res = call_gemini(prompt=text, model="gemini-2.5-flash-lite")
    return label, res

with concurrent.futures.ThreadPoolExecutor(max_workers=5) as pool:
    results = list(pool.map(worker, prompts))

for label, response in results:
    print(f"=== {label} ===\n{response[:100]}...\n")

5. Quick CLI / Curl Verification

Test an API key and connectivity from the shell in one line:

curl -s -X POST \
  "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash-lite:generateContent?key=${GEMINI_API_KEY}" \
  -H "Content-Type: application/json" \
  -d '{"contents":[{"parts":[{"text":"Reply with: API CONNECTION SUCCESSFUL"}]}]}' \
  | grep -o '"text": *"[^"]*"'

6. Critical Rules & Gotchas

  1. System Instructions Placement: Never put system prompts in contents. Always place them in the dedicated top-level system_instruction: {"parts": [{"text": "..."}]} block.
  2. Key Security: Never commit raw API keys to Git, Fig, Piper, or review CLs. Always read from os.environ["GEMINI_API_KEY"].
  3. Candidate Parsing: Always guard access: res.get("candidates", [])[0].get("content", {}).get("parts", [])[0].get("text", ""). If a response is blocked by safety filters, candidates[0].content.parts may be empty. Check finishReason if text is blank.
  4. Timeouts: Wrap urlopen in explicit timeouts (timeout=60 or 90) to prevent hanging processes on network partitions.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.