agentleFS
kumaran-iskumaran-is/claude-code-onboarding/.claude/skills/google-adk/SKILL.md

google-adk

Skill35 starsChanged 6 months agoMITView on GitHub

Google ADK (Agent Development Kit) Python skill. Use when building AI agents with google-adk, Gemini models, SequentialAgent, ParallelAgent, LoopAgent, FunctionTool, McpToolset, session management, memory services, artifact storage, callbacks, or FastAPI integration for ADK agents.

  • Reads credentials

4 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

9 rules. 0 are common, 6 are distinctive, and 3 are very specific to this project.

  • 0

    Common

    Most of the 4 edited versions we read keep these.

  • 6

    Distinctive

    This author's own choices. Worth a look.

  • 3

    Very specific

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

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    NEVER call the real Gemini API in unit tests: Always use InMemoryRunner for tests.

    line 19
  2. Very specific:

    NEVER connect to external services from a FunctionTool: All external I/O (HTTP, DB, vector DB, cloud APIs) belongs in MCPTools accessed via …

    line 21
  3. Distinctive:

    Before writing any tool, apply this binary test:

    line 92
  4. Very specific:

    ToolContext exception: If a tool needs BOTH external data AND ToolContext session state, it MUST be a FunctionTool — only in-process tools …

    line 101
  5. Distinctive:

    Write golden test cases BEFORE writing agent code.

    line 107
  6. Distinctive:

    Write at minimum: one happy-path case, one error-path case, one edge-case

    line 111
  7. Distinctive:

    Run eval skeleton to confirm test infrastructure works

    line 113
  8. Distinctive:

    All error paths must:

    line 210
  9. Distinctive:

    After implementing any ADK agent feature:

    line 217

“Common” is measured: kept by at least 6 in 10 of the 4 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

Google ADK Development Skill — Python + Gemini + FastAPI

Iron Law

NEVER call the real Gemini API in unit tests. Always use InMemoryRunner for tests. Production agents use Runner with real session services. Mixing these means real API costs, flaky tests, and non-deterministic CI.

NEVER connect to external services from a FunctionTool. All external I/O (HTTP, DB, vector DB, cloud APIs) belongs in MCPTools accessed via McpToolset. FunctionTools contain ONLY pure logic or session state access.

ALWAYS use McpToolset for MCP connections — never instantiate McpToolset(connection_params=...) directly in agent code; use the factory provided by your project. Rules:

  • tool_filter is MANDATORY and non-empty in every McpToolset call — limits which MCP tools the LLM can call; empty list raises ValueError at startup
  • NEVER bypass McpToolset with direct httpx/requests calls — all external I/O routes through the MCP server via McpToolset

Quick Scaffold (Two Options)

Option A: agent-starter-pack (Recommended for production)

uvx agent-starter-pack create my-agent --agent adk --prototype --agent-guidance-filename CLAUDE.md -y
# Templates: adk (default), adk_a2a (A2A protocol), agentic_rag (RAG)

Generates project with Terraform, Dockerfile, CI/CD, eval harness. Use enhance to add deployment later.

Option B: Manual setup (Simpler, no deployment scaffold)

uv init my-adk-service && cd my-adk-service
uv add google-adk "google-genai>=1.0.0" "fastapi>=0.135.2" "uvicorn[standard]" pydantic pydantic-settings structlog
uv add --dev pytest pytest-asyncio httpx ruff mypy

Option C: Enhance existing project (add deployment to scaffolded project)

uvx agent-starter-pack enhance .

Choose deployment target when prompted: cloud_run or agent_engine.

Process

  1. Write DESIGN_SPEC.md — Before any code, write a spec covering: purpose, example use cases, required tools, safety constraints, success criteria, edge cases. Save as DESIGN_SPEC.md in the project root. This is your contract — all implementation must align with it.
  2. Scaffold — uv init + install google-adk + google-genai; confirm uv add "google-adk>=1.28.0" resolves without error
  3. Configure — .env with GOOGLE_API_KEY / GOOGLE_CLOUD_PROJECT; load via pydantic-settings BaseSettings; never hardcode keys
  4. Define Agent — Agent(name, model, instruction, tools) using model="gemini-3.1-flash"; write docstrings on every tool function
  5. Compose Agents — use SequentialAgent, ParallelAgent, or LoopAgent for multi-step workflows; set output_key on each sub-agent that passes state downstream
  6. Define Tools — plain Python functions with type hints and docstrings; use pydantic.BaseModel for complex inputs; accept tool_context: ToolContext to read/write session state
  7. Add Callbacks — before_model_callback, after_model_callback, before_tool_callback, after_tool_callback, on_model_error_callback, on_tool_error_callback for rate limiting, logging, and structured error handling
  8. Session Management — InMemorySessionService() for dev/test; VertexAiSessionService(project_id, location) for production; always call create_session before first runner.run
  9. Add Memory — InMemoryMemoryService for dev; pass memory_service to Runner; add load_memory built-in tool to agents that need long-term recall
  10. Expose API — FastAPI routes using runner.run_async() with StreamingResponse for SSE; one Runner instance per app lifecycle
  11. Write Tests — InMemoryRunner for unit tests; pytest-asyncio for async tests; test tools in isolation, then agent routing end-to-end
  12. Deploy — Docker + uvicorn; inject GOOGLE_API_KEY as env var; use GOOGLE_CLOUD_PROJECT + GOOGLE_CLOUD_LOCATION for Vertex AI session service in prod

Key Patterns

PatternImplementationReference
Single AgentAgent(name, model, instruction, tools)adk-core-patterns.md
Sequential PipelineSequentialAgent(sub_agents=[a, b, c]) + output_key per agentadk-agent-types.md
Parallel AnalysisParallelAgent(sub_agents=[...]) + output_key per agentadk-agent-types.md
Iterative RefinementLoopAgent(sub_agents=[...], max_iterations=N) + exit_loopadk-agent-types.md
Agent Handofftransfer_to_agent built-in + sub_agents=[...] on rootadk-agent-handoff.md
Custom ToolsPlain function with docstring + ToolContext for stateadk-tools-basic.md
MCP IntegrationMcpToolset(connection_params=StdioConnectionParams(...))adk-tools-basic.md
Structured Outputoutput_schema=PydanticModel + output_key="key"adk-core-patterns.md
Callbacksbefore_model_callback, after_model_callback, before_tool_callbackadk-tools-callbacks.md
Session Statetool_context.state["key"] read/writeadk-core-patterns.md
MemoryInMemoryMemoryService + load_memory tooladk-memory-artifacts.md
TestingInMemoryRunner + pytest-asyncioadk-testing.md
FastAPI SSErunner.run_async() + StreamingResponseadk-fastapi-integration.md
Evaluationadk eval + evalset schema + LLM-as-judgeSee Google ADK docs
DeploymentAgent Engine, Cloud Run, CI/CDSee Google ADK docs
ObservabilityCloud Trace, prompt logging, agent analyticsSee Google ADK docs

R1/R2 Tool Placement Rule

Before writing any tool, apply this binary test:

"Does this tool perform I/O outside the agent process (DB, HTTP, vector DB, cloud APIs)?"

AnswerTool typeLocation
YESR1 — MCPToolMCP server — agent accesses via McpToolset
NOR2 — FunctionToolAgent tools directory — pure logic only

ToolContext exception: If a tool needs BOTH external data AND ToolContext session state, it MUST be a FunctionTool — only in-process tools can access ToolContext. The FunctionTool reads data from session state previously populated by an MCPTool.

NEVER put import httpx, import sqlalchemy, or import requests in FunctionTool files.

Eval-First Development

Write golden test cases BEFORE writing agent code. This prevents writing code that passes no evaluation criteria.

Order of operations:

  1. Define tests/golden/agents/<agent_name>/ directory
  2. Write at minimum: one happy-path case, one error-path case, one edge-case
  3. Each case: input → expected output with confidence_min, contains_keywords, or pattern_* assertions
  4. Run eval skeleton to confirm test infrastructure works
  5. THEN implement the agent
  6. Iterate until all golden cases pass

Eval Skeleton (generate this first, before implementing the agent)

AGENT=my_agent  # replace with your agent name
mkdir -p tests/golden/agents/$AGENT tests/evals

# Placeholder evalset
cat > tests/evals/$AGENT.evalset.json << 'JSON'
[
  {
    "name": "happy_path_1",
    "input": { "query": "your test input here" },
    "expected_tool_use": [{ "tool_name": "your_tool_name" }],
    "expected_final_response": { "contains": "expected keyword" }
  }
]
JSON

# Eval config with accuracy threshold
cat > tests/evals/eval_config.json << 'JSON'
{
  "criteria": [
    { "type": "tool_trajectory_avg_score", "config": { "match_type": "IN_ORDER" } },
    { "type": "final_response_match_v2", "config": { "threshold": 0.8 } }
  ]
}
JSON

Code Preservation Rules

  • NEVER change the model in existing code unless explicitly asked — changing gemini-3.1-flash to another model is a breaking change
  • NEVER rewrite working agent code — if the agent works, refactor incrementally
  • NEVER remove tools from an agent without explicit approval — tools are part of the agent's contract
  • NEVER rename output_key values — downstream agents reference them by name

Documentation Sources

SourceURL / ToolPurpose
Google ADK Pythonhttps://context7.com/google/adk-python/llms.txtOfficial ADK API reference
Google GenAI typesContext7 MCP — resolve google-genaitypes.Part, types.Content, GenerateContentConfig
Pydantic v2Context7 MCP — resolve pydanticBaseModel, Field, validators
ADK Docs MCPadk-docs MCP server (installed)Live ADK documentation

Reference Files

FileContents
reference/adk-core-patterns.mdAgent config, Runner patterns (sync/async), App class, session management
reference/adk-structured-output.mdSession state access, structured output schemas, UserContent construction
reference/adk-agent-types.mdSequentialAgent, ParallelAgent, LoopAgent, composition patterns
reference/adk-agent-handoff.mdAgent handoff via transfer_to_agent, output_key state passing rules
reference/adk-tools-basic.mdFunctionTool, ToolContext, async tools, Pydantic inputs, McpToolset (all 4 connection modes)
reference/adk-tools-callbacks.mdCallbacks: before/after model, on_model_error, before/after tool, on_tool_error
reference/adk-memory-artifacts.mdMemory services, load_memory tool, artifact storage, semantic search
reference/adk-fastapi-integration.mdFastAPI + StreamingResponse SSE, lifespan runner setup, request/response models
reference/adk-testing.mdInMemoryRunner unit tests, pytest-asyncio patterns, tool isolation, agent routing
reference/adk-project-config.mdpyproject.toml, .env setup, directory structure, Dockerfile, logging, commands
reference/adk-gemini-prompt-templates.mdGemini-specific LlmAgent instruction templates — base structure, RAG with citations, constitutional AI (2-agent SequentialAgent), Tree-of-Thoughts, multi-step analysis, model selection guide (Flash vs Pro)

Common Commands

# Run dev server via ADK web UI
adk web

# Run FastAPI app with uvicorn
uvicorn src.main:app --reload --port 8000

# Run tests
uv run pytest tests/ -v

# Type check
uv run mypy src/

# Lint + format
uv run ruff check src/ && uv run ruff format src/

# Install all deps from lockfile
uv sync

Error Handling

ADK-specific error handling rules:

  • Provider errors — wrap runner.run() / runner.run_async() in try/except; catch google.api_core.exceptions.GoogleAPICallError; log with full context (user_id, session_id, model); rethrow or return structured error response — never swallow
  • Tool errors — use on_tool_error_callback to intercept and log; return a descriptive error string from tools (ADK surfaces it to the model); never return empty string or None silently
  • Loop limits — LoopAgent stops at max_iterations; ensure exit_loop is called by the agent's instruction before the limit; log when loop exits by limit vs. by tool call
  • Callback abort — returning a non-None value from before_model_callback skips the model call; document this explicitly in the callback with a comment
  • Session not found — always call session_service.get_session() before runner.run(); if None, call create_session() first

All error paths must:

  1. Log with structured logger (structlog) including user_id, session_id, agent_name
  2. Either rethrow or return an error state — no silent empty returns
  3. Surface the failure to the user (API error response, SSE error event)

Post-Code Review

After implementing any ADK agent feature:

  1. Dispatch agentic-ai-reviewer agent — pass the agent graph structure and tool implementations
  2. Dispatch security-reviewer — flag any tool that calls external APIs or handles user PII
  3. Confirm: no hardcoded API keys, all inputs validated, all error paths logged

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.