This page explains how to create custom tools using Python functions in ADK. Custom tools allow agents to execute user-defined logic, call external APIs, perform computations, or interact with any system that can be accessed via Python code.
Scope: This page covers creating tools from Python functions and configuring them in agents. For other tool types, see Tool Framework for BaseTool and BaseToolset abstractions, OpenAPI Tools for REST API integration, MCP Tools for Model Context Protocol integration, and BigQuery Tools for database operations.
Custom tools in ADK can be created by writing standard Python functions. The framework automatically converts these functions into tools that agents can call. This conversion is handled by the FunctionTool wrapper, which introspects the function signature to generate appropriate tool declarations for LLM models.
Architecture: Custom Tool Integration
Sources: src/google/adk/agents/llm_agent.py132-180 Diagram 3 from system architecture
The simplest way to create a custom tool is to write a Python function and add it to the agent's tools list.
The function's docstring becomes the tool description, and type hints define parameter types. The framework automatically generates a FunctionDeclaration that the LLM can use to call this tool.
Conversion Process:
Sources: src/google/adk/agents/llm_agent.py135-180 src/google/adk/agents/llm_agent.py566-584
ADK uses Python type hints to define tool parameters for the LLM:
Supported types include:
str, int, float, boolOptional[T]List[T], dictEnum subclasses (see src/google/adk/agents/llm_agent_config.py247)Sources: src/google/adk/agents/llm_agent_config.py145-199 CHANGELOG.md references to enum support
The FunctionTool class wraps Python functions and provides the BaseTool interface required by agents. This conversion happens automatically when you pass a callable to the tools parameter.
Automatic Wrapping Logic:
The conversion happens in _convert_tool_union_to_tools():
Sources: src/google/adk/agents/llm_agent.py135-180
The FunctionTool wrapper:
inspect moduleFunctionDeclaration for the LLMTools can access session state, artifacts, and services by accepting a ToolContext parameter:
ToolContext Contents:
| Field | Type | Description |
|---|---|---|
session_state | dict | Session-level state dictionary |
user_state | dict | User-level state (shared across sessions) |
app_state | dict | App-level state (shared across users) |
user_id | str | Current user identifier |
session_id | str | Current session identifier |
session_service | BaseSessionService | Session persistence service |
artifact_service | BaseArtifactService | Artifact storage service |
memory_service | BaseMemoryService | Long-term memory service |
The framework automatically passes the ToolContext when a parameter is named context and typed as ToolContext.
Sources: System architecture Diagram 3 (Tool Execution section), src/google/adk/agents/llm_agent.py99-100
Custom tools can be configured in Python code or YAML configuration files.
Direct assignment to the tools parameter:
Tools can be referenced in YAML agent configuration files using fully qualified names.
Tool Definition (my_tools.py):
Agent Configuration (agent.yaml):
Tool Resolution Flow:
Sources: src/google/adk/agents/llm_agent_config.py145-199 src/google/adk/agents/config_agent_utils.py842-896
For tools that require initialization arguments, use the args syntax:
Python tool factory:
YAML configuration:
Resolution Process:
The _resolve_tools method src/google/adk/agents/config_agent_utils.py842-896 handles different tool configuration patterns:
| Tool Type | Detection | Resolution |
|---|---|---|
| Built-in tool | No '.' in name | Import from google.adk.tools |
| User-defined instance | Object is BaseTool/BaseToolset | Use directly |
| User-defined class | Class is subclass of BaseTool/BaseToolset | Call from_config(args) |
| Tool factory function | Callable with args | Call function with args |
| Function tool | Callable without args | Wrap in FunctionTool |
Sources: src/google/adk/agents/config_agent_utils.py842-896 src/google/adk/tools/tool_configs.py42-129
When an agent is loaded, ADK resolves all tool references through a multi-step pipeline.
Complete Tool Resolution Pipeline:
Sources: src/google/adk/agents/llm_agent.py566-584 src/google/adk/agents/llm_agent.py135-180
Special Cases:
GoogleSearchTool and VertexAiSearchTool are wrapped when used with other tools due to built-in tool limitations src/google/adk/agents/llm_agent.py146-172BaseToolset instances expand into multiple tools via get_tools_with_prefix() src/google/adk/agents/llm_agent.py180_resolve_tools() src/google/adk/agents/config_agent_utils.py842-896Tools should handle errors gracefully and return informative error messages:
Use ToolContext to persist information across tool calls:
Test tools independently before integrating with agents:
Sources: CONTRIBUTING.md testing guidelines, tests/unittests/agents/test_agent_config.py examples
Custom tools in ADK are created by writing standard Python functions and adding them to the agent's tools list. The framework automatically wraps these functions in FunctionTool, which handles introspection, declaration generation, and execution. Tools can access session state and services via ToolContext parameters, and can be configured in Python code or YAML files. The tool resolution pipeline ensures proper loading and initialization of all tool types.
Sources: src/google/adk/agents/llm_agent.py132-180 src/google/adk/agents/llm_agent.py566-584 src/google/adk/agents/llm_agent_config.py145-199 src/google/adk/agents/config_agent_utils.py842-896 src/google/adk/tools/tool_configs.py
Refresh this wiki
This wiki was recently refreshed. Please wait 5 days to refresh again.