Google Agent Development Kit (ADK) 指南 第五章:工具集成与自定义
系列教程:这是《Google ADK 指南》系列的第五章。
前置知识:已完成第四章,掌握 Agent 开发。
目录
1. 工具基础
1.1 工具的作用
工具是 Agent 的"手和脚",让 AI 能够:
- 🔍 获取信息:搜索、查询数据库
- 📝 执行操作:创建订单、发送邮件
- 🔗 集成系统:连接 CRM、ERP
- 📊 处理数据:计算、分析、转换
1.2 工具类型
| 类型 | 说明 | 示例 |
|---|---|---|
| 函数工具 | Python 函数 | 计算器、日期处理 |
| HTTP 工具 | REST API | 天气、地图、支付 |
| 数据库工具 | SQL 查询 | 订单、用户查询 |
| GCP 工具 | Google 服务 | BigQuery、Storage |
| 代码工具 | 执行代码 | Python、JavaScript |
1.3 工具签名
python
from google.adk import Tool
from pydantic import BaseModel, Field
@Tool(
# 基础信息
name="calculate_shipping",
description="计算运费,支持国内和国际",
# 参数定义(Pydantic)
parameters={
"weight": {
"type": "number",
"description": "包裹重量(公斤)",
"required": True
},
"destination": {
"type": "string",
"description": "目的地城市",
"required": True
},
"express": {
"type": "boolean",
"description": "是否选择快递",
"default": False
}
},
# 高级配置
timeout=10, # 超时(秒)
cache_ttl=300, # 缓存时间(秒)
rate_limit=100, # 每分钟限制
requires_auth=True # 需要认证
)
def calculate_shipping(weight: float, destination: str, express: bool = False) -> str:
"""计算运费并返回格式化结果"""
# 实现...
pass
2. 内置工具
2.1 搜索工具
python
from google.adk.tools import GoogleSearchTool
# Google 搜索
search_tool = GoogleSearchTool(
api_key="your_search_api_key",
cse_id="your_cse_id",
num_results=5
)
# 使用
@Agent(tools=[search_tool])
def search_agent(query: str):
return agent.run(f"搜索:{query}")
2.2 计算工具
python
from google.adk.tools import CalculatorTool
calculator = CalculatorTool(
supported_operations=["+", "-", "*", "/", "^", "sqrt", "log"]
)
# 示例
response = agent.run("计算 (123 + 456) * 789")
2.3 日期时间工具
python
from google.adk.tools import DateTimeTool
datetime_tool = DateTimeTool(
timezone="Asia/Shanghai",
locale="zh_CN"
)
# 可用功能
# - 获取当前时间
# - 日期计算
# - 时区转换
# - 格式化输出
2.4 文件工具
python
from google.adk.tools import FileTool
file_tool = FileTool(
base_dir="/data",
allowed_extensions=[".txt", ".pdf", ".docx"],
max_file_size=10 * 1024 * 1024 # 10MB
)
# 可用功能
# - 读取文件
# - 写入文件
# - 搜索文件
# - 文件转换
3. 自定义工具开发
3.1 简单函数工具
python
from google.adk import Tool
@Tool(
name="get_weather",
description="获取城市天气信息",
parameters={
"city": {"type": "string", "description": "城市名称"},
"date": {"type": "string", "description": "日期(YYYY-MM-DD),默认今天"}
}
)
def get_weather(city: str, date: str = None) -> str:
"""获取天气信息"""
import requests
api_key = "your_weather_api_key"
url = "http://api.weatherapi.com/v1/forecast.json"
params = {"key": api_key, "q": city, "days": 1}
response = requests.get(url, params=params)
data = response.json()
current = data["current"]
return f"{city} 天气:{current['condition']['text']}, 温度:{current['temp_c']}°C"
3.2 类工具(复杂逻辑)
python
from google.adk.tools import BaseTool
from pydantic import BaseModel, Field
from typing import Optional
class OrderManagementTool(BaseTool):
"""订单管理工具"""
name = "order_management"
description = "管理订单:查询、创建、取消"
# 参数定义
class Parameters(BaseModel):
action: str = Field(..., description="操作类型:query/create/cancel")
order_id: Optional[str] = Field(None, description="订单 ID")
items: Optional[list] = Field(None, description="商品列表")
user_id: str = Field(..., description="用户 ID")
def __init__(self, db_connection):
self.db = db_connection
def execute(self, action: str, order_id: str = None,
items: list = None, user_id: str = None) -> dict:
if action == "query":
return self._query_order(order_id)
elif action == "create":
return self._create_order(items, user_id)
elif action == "cancel":
return self._cancel_order(order_id)
else:
raise ValueError(f"未知操作:{action}")
def _query_order(self, order_id: str) -> dict:
order = self.db.query("SELECT * FROM orders WHERE id=?", order_id)
return {"status": "success", "order": order}
def _create_order(self, items: list, user_id: str) -> dict:
order_id = self.db.insert("orders", {"user_id": user_id, "items": items})
return {"status": "success", "order_id": order_id}
def _cancel_order(self, order_id: str) -> dict:
self.db.update("orders", {"status": "cancelled"}, {"id": order_id})
return {"status": "success", "message": "订单已取消"}
# 使用
order_tool = OrderManagementTool(db_connection)
agent = Agent(tools=[order_tool])
3.3 异步工具
python
from google.adk import Tool
import aiohttp
@Tool(
name="fetch_webpage",
description="获取网页内容",
parameters={
"url": {"type": "string", "description": "网页 URL"}
}
)
async def fetch_webpage(url: str) -> str:
"""异步获取网页内容"""
async with aiohttp.ClientSession() as session:
async with session.get(url) as response:
return await response.text()
3.4 带状态的工具
python
from google.adk.tools import StatefulTool
class ShoppingCartTool(StatefulTool):
"""购物车工具(带状态)"""
name = "shopping_cart"
description = "管理购物车:添加、删除、结算"
def __init__(self):
self.carts = {} # user_id -> cart_items
def add_item(self, user_id: str, item: dict):
if user_id not in self.carts:
self.carts[user_id] = []
self.carts[user_id].append(item)
return {"status": "success", "cart": self.carts[user_id]}
def remove_item(self, user_id: str, item_id: str):
if user_id in self.carts:
self.carts[user_id] = [
i for i in self.carts[user_id] if i["id"] != item_id
]
return {"status": "success", "cart": self.carts.get(user_id, [])}
def checkout(self, user_id: str) -> dict:
items = self.carts.get(user_id, [])
total = sum(item["price"] * item["quantity"] for item in items)
self.carts[user_id] = [] # 清空购物车
return {"status": "success", "total": total, "items": len(items)}
4. 第三方 API 集成
4.1 REST API 工具
python
from google.adk import Tool
import requests
from functools import wraps
def api_tool(base_url: str, api_key: str):
"""API 工具装饰器"""
def decorator(func):
@wraps(func)
@Tool(
name=func.__name__,
description=func.__doc__,
timeout=30
)
def wrapper(*args, **kwargs):
headers = {"Authorization": f"Bearer {api_key}"}
try:
result = func(base_url=base_url, headers=headers, *args, **kwargs)
return result
except requests.exceptions.RequestException as e:
return f"API 调用失败:{str(e)}"
return wrapper
return decorator
# 使用示例
@api_tool("https://api.stripe.com", "sk_test_xxx")
def create_charge(base_url: str, headers: dict, amount: int, currency: str) -> dict:
"""创建支付订单"""
response = requests.post(
f"{base_url}/v1/charges",
headers=headers,
data={"amount": amount, "currency": currency}
)
return response.json()
4.2 GraphQL API 工具
python
from google.adk import Tool
from gql import gql, Client
from gql.transport.requests import RequestsHTTPTransport
@Tool(
name="github_query",
description="查询 GitHub 数据",
parameters={
"query": {"type": "string", "description": "GraphQL 查询"}
}
)
def github_query(query: str) -> dict:
"""执行 GitHub GraphQL 查询"""
transport = RequestsHTTPTransport(
url="https://api.github.com/graphql",
headers={"Authorization": "Bearer YOUR_TOKEN"},
verify=True,
retries=3
)
client = Client(transport=transport, fetch_schema_from_transport=True)
result = client.execute(gql(query))
return result
4.3 WebSocket 工具
python
from google.adk.tools import BaseTool
import websocket
import json
class StockPriceTool(BaseTool):
"""股票价格工具(WebSocket 实时)"""
name = "stock_price"
description = "获取实时股票价格"
def __init__(self, ws_url: str):
self.ws_url = ws_url
self.ws = None
def connect(self):
self.ws = websocket.create_connection(self.ws_url)
def execute(self, symbol: str) -> dict:
if not self.ws:
self.connect()
# 订阅股票
self.ws.send(json.dumps({"action": "subscribe", "symbol": symbol}))
# 接收价格
response = self.ws.recv()
return json.loads(response)
def close(self):
if self.ws:
self.ws.close()
5. GCP 服务集成
5.1 BigQuery 工具
python
from google.adk import Tool
from google.cloud import bigquery
@Tool(
name="bigquery_query",
description="执行 BigQuery SQL 查询",
parameters={
"query": {"type": "string", "description": "SQL 查询语句"},
"project_id": {"type": "string", "description": "GCP 项目 ID"}
}
)
def bigquery_query(query: str, project_id: str) -> list:
"""执行 BigQuery 查询"""
client = bigquery.Client(project=project_id)
# 只读检查
if not query.strip().upper().startswith("SELECT"):
return {"error": "只允许 SELECT 查询"}
query_job = client.query(query)
results = query_job.result()
return [dict(row) for row in results]
5.2 Cloud Storage 工具
python
from google.adk import Tool
from google.cloud import storage
@Tool(
name="gcs_upload",
description="上传文件到 Cloud Storage",
parameters={
"bucket": {"type": "string", "description": "存储桶名称"},
"source_path": {"type": "string", "description": "本地文件路径"},
"destination": {"type": "string", "description": "目标路径"}
}
)
def gcs_upload(bucket: str, source_path: str, destination: str) -> dict:
"""上传文件到 GCS"""
client = storage.Client()
bucket = client.bucket(bucket)
blob = bucket.blob(destination)
blob.upload_from_filename(source_path)
return {
"status": "success",
"gs_uri": f"gs://{bucket}/{destination}",
"public_url": f"https://storage.googleapis.com/{bucket}/{destination}"
}
5.3 Vertex AI 工具
python
from google.adk import Tool
from vertexai.preview.generative_models import GenerativeModel
@Tool(
name="vertex_generate",
description="使用 Vertex AI 生成内容",
parameters={
"prompt": {"type": "string", "description": "生成提示"},
"model": {"type": "string", "description": "模型名称", "default": "gemini-pro"}
}
)
def vertex_generate(prompt: str, model: str = "gemini-pro") -> str:
"""使用 Vertex AI 生成内容"""
generative_model = GenerativeModel(model)
response = generative_model.generate_content(prompt)
return response.text
5.4 Secret Manager 工具
python
from google.adk import Tool
from google.cloud import secretmanager
@Tool(
name="get_secret",
description="从 Secret Manager 获取密钥",
parameters={
"secret_id": {"type": "string", "description": "密钥 ID"},
"project_id": {"type": "string", "description": "GCP 项目 ID"}
},
requires_auth=True
)
def get_secret(secret_id: str, project_id: str) -> str:
"""获取密钥"""
client = secretmanager.SecretManagerServiceClient()
name = f"projects/{project_id}/secrets/{secret_id}/versions/latest"
response = client.access_secret_version(request={"name": name})
return response.payload.data.decode("UTF-8")
6. 工具管理最佳实践
6.1 工具组织
python
# 按功能分组
from google.adk.tools import ToolGroup
search_tools = ToolGroup([
google_search_tool,
internal_search_tool,
vector_search_tool
])
data_tools = ToolGroup([
bigquery_tool,
sql_tool,
analytics_tool
])
communication_tools = ToolGroup([
email_tool,
sms_tool,
slack_tool
])
# Agent 使用
agent = Agent(tools=[search_tools, data_tools, communication_tools])
6.2 错误处理
python
from google.adk.tools import ToolExecutionError
@Tool(name="reliable_tool")
def reliable_tool(param: str) -> dict:
"""可靠的工具实现"""
try:
# 主逻辑
result = do_something(param)
return {"status": "success", "data": result}
except ValidationError as e:
# 参数验证失败
return {"status": "error", "code": "VALIDATION_ERROR", "message": str(e)}
except APIError as e:
# API 错误
return {"status": "error", "code": "API_ERROR", "message": str(e)}
except TimeoutError:
# 超时
return {"status": "error", "code": "TIMEOUT", "message": "请求超时"}
except Exception as e:
# 未知错误
logger.exception("未知错误")
return {"status": "error", "code": "UNKNOWN", "message": "内部错误"}
6.3 日志与监控
python
from google.adk.tools import MonitoredTool
@Tool(
name="monitored_tool",
monitor=True, # 启用监控
log_level="INFO"
)
def monitored_tool(param: str) -> str:
"""带监控的工具"""
# 自动记录:
# - 输入参数
# - 执行时间
# - 输出结果
# - 错误信息
pass
6.4 测试工具
python
import pytest
from google.adk.tools import ToolTester
def test_weather_tool():
tool = get_weather
# 测试正常情况
result = tool.execute(city="北京")
assert "天气" in result
assert "°C" in result
# 测试错误情况
result = tool.execute(city="无效城市")
assert "error" in result.lower() or "失败" in result
# 使用测试器
tester = ToolTester(get_weather)
tester.test_with_inputs([
{"city": "北京"},
{"city": "上海"},
{"city": ""} # 边界测试
])
系列教程导航:
- 第一章:ADK 简介与对比
- 第二章:环境搭建与快速开始
- 第三章:核心概念与架构
- 第四章:Agent 开发与编排
- 第五章:工具集成与自定义 ← 本章
- 第六章:记忆与状态管理
- 第七章:企业级功能与安全
- 第八章:实战案例与最佳实践