All skills
google avatar

/adk-agent-builder

@29933ce
by googlegoogle/adk-python22k stars
4,084

Builds ADK (Agent Development Kit) Python agents: LLM agents with tools, graph workflows of function and agent nodes, conditional routing, fan-out and join, schema-validated delegation between agents, human-in-the-loop pauses, and pytest coverage for all of it. Use when asked to create an agent or a workflow, add a tool to one, branch or loop between nodes, run steps in parallel, pause for user approval, or test an agent. Don't use for explaining how ADK works internally or designing its core components (use `adk-architecture`), for an agent that already runs but misbehaves (use `adk-debug`), for authoring a sample under `contributing/` (use `adk-sample-creator`), or for naming, typing, and formatting conventions (use `adk-style`).

Use this Skill: https://skilld.dev/gh/google/adk-python/adk-agent-builder

This session only. Nothing lands on disk.

referencestool-catalog.md

≈1.4k tokens on demand. Your agent reads this file only when SKILL.md points to it.

Tool Catalog

Every way to give an agent a capability, from a plain Python function to a whole remote API.

Python functions

Pass callables straight to tools=. The name, docstring, and type hints become the schema the model sees, so all three are load-bearing — an undocumented or untyped parameter is invisible to the model.

def get_weather(city: str, unit: str = 'celsius') -> str:
  """Get the current weather for a city.

  Args:
    city: The city name to look up.
    unit: Temperature unit, 'celsius' or 'fahrenheit'.

  Returns:
    A string with the weather information.
  """
  return f'Sunny, 22 degrees {unit} in {city}'


root_agent = Agent(tools=[get_weather], ...)

Sync and async both work.

Getting the context inside a tool

Add a parameter annotated with ToolContext (or Context / CallbackContext — they are all the same class). It is matched by annotation, not by name, and excluded from the schema the model sees. A parameter literally named tool_context is used as a fallback when no annotation matches.

from google.adk.tools import ToolContext


async def my_tool(query: str, tool_context: ToolContext) -> str:
  tool_context.state['key'] = 'value'
  await tool_context.save_artifact('f.txt', part)
  results = await tool_context.search_memory('q')
  return 'done'

A parameter named input_stream is also excluded, for streaming tools.

Built-in tools

Tool Import from google.adk.tools
google_search Google Search grounding
url_context Fetch and ground on URLs in the prompt
load_artifacts Pull session artifacts into context
load_memory / preload_memory Query long-term memory
exit_loop Break out of a LoopAgent
transfer_to_agent Hand control to another agent
get_user_choice Ask the user to pick an option
google_maps_grounding, enterprise_web_search Other grounding sources

Long-running tools

LongRunningFunctionTool returns its result asynchronously against the original function_call_id, which is how an agent pauses for a human.

from google.adk.tools import LongRunningFunctionTool


def approve_expense(amount: float) -> dict:
  """Submit an expense for approval."""
  return {'status': 'pending', 'id': 'exp-123'}


root_agent = Agent(tools=[LongRunningFunctionTool(approve_expense)], ...)

Workflows and @node functions as tools

Pass a Workflow (with input_schema set to a Pydantic BaseModel) or a @node-decorated function straight into tools=. The agent runs it in an isolated sub-branch ({tool_name}@{function_call_id}) and receives the terminal output.

Set ctx.actions.skip_summarization = True inside the node when its output should be emitted directly as the final user-visible text response without a follow-up LLM summarization turn:

from google.adk import Agent, Context
from google.adk.workflow import node


@node
def generate_report(project: str, ctx: Context) -> str:
  """Generate a status report for a project."""
  ctx.actions.skip_summarization = True
  return f'Report for {project}: Ready'


root_agent = Agent(tools=[generate_report], ...)

MCP servers

from google.adk.tools.mcp_tool import McpToolset, StdioConnectionParams
from mcp import StdioServerParameters

root_agent = Agent(
    tools=[
        McpToolset(
            connection_params=StdioConnectionParams(
                server_params=StdioServerParameters(
                    command='npx',
                    args=['-y', '@modelcontextprotocol/server-filesystem', '/path'],
                ),
                timeout=5,
            ),
            tool_filter=['read_file', 'list_directory'],
        )
    ],
    ...
)

Connection classes: StdioConnectionParams, SseConnectionParams, StreamableHTTPConnectionParams.

Needs pip install mcp. StdioServerParameters comes from that package, not from ADK. Use McpToolset; the all-caps MCPToolset still resolves but warns.

OpenAPI specs

from google.adk.tools.openapi_tool import OpenAPIToolset

toolset = OpenAPIToolset(spec_str=open('openapi.yaml').read(), spec_str_type='yaml')
root_agent = Agent(tools=[toolset], ...)

spec_str_type is 'json' (the default) or 'yaml'. Pass spec_dict= instead to skip parsing. RestApiTool from the same module wraps a single endpoint.

Google API toolsets

Generated from Google's API discovery documents. BigQueryToolset, CalendarToolset, and their siblings all take the same arguments.

from google.adk.tools.google_api_tool.google_api_toolsets import BigQueryToolset

bigquery = BigQueryToolset(
    client_id='...',
    client_secret='...',
    tool_filter=['bigquery_datasets_list'],
)

Also accepted: service_account= instead of the OAuth pair, and tool_name_prefix= to namespace the generated tool names.

Code execution

The code executor is its own agent field, not a tool.

from google.adk.code_executors.built_in_code_executor import BuiltInCodeExecutor

root_agent = Agent(code_executor=BuiltInCodeExecutor(), ...)

Custom BaseTool

from google.adk.tools import BaseTool
from google.genai import types


class MyTool(BaseTool):

  def __init__(self):
    super().__init__(name='my_tool', description='Does something.')

  def _get_declaration(self):
    return types.FunctionDeclaration(
        name=self.name,
        description=self.description,
        parameters_json_schema={
            'type': 'object',
            'properties': {'param': {'type': 'string'}},
            'required': ['param'],
        },
    )

  async def run_async(self, *, args, tool_context):
    return {'result': args['param']}

Custom BaseToolset

A toolset supplies tools dynamically, so the set can depend on context.

from google.adk.tools.base_toolset import BaseToolset


class MyToolset(BaseToolset):

  def __init__(self):
    super().__init__(tool_filter=None, tool_name_prefix='my')

  async def get_tools(self, readonly_context=None):
    return [ToolA(), ToolB()]

  async def process_llm_request(self, *, tool_context, llm_request):
    llm_request.append_instructions(['Custom instruction'])

tool_filter is a list of tool names or a ToolPredicate callable; tool_name_prefix renames every tool the toolset returns, which is how you keep two toolsets from colliding.

Source: SKILL.md on GitHub

No alerts7d3 checks · Risk SAFE
  • Gen Agent Trust Hub7d

    This skill provides comprehensive documentation and reference material for building agents using the Google Agent Development Kit (ADK). It covers workflow orchestration, tool usage, and includes guidance on security best practices like input validation and secure credential management. No security issues were detected.

  • Socket7d

    No alerts

  • Snyk7d

    Risk: LOW · No issues

Signed by skilld at 29933ce. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub yesterday.

Activeupdated 2 months ago

README badge

README badge for google/adk-python/adk-agent-builder