Google Agent Development Kit (ADK) 指南 第五章:工具集成与自定义

Google Agent Development Kit (ADK) 指南 第五章:工具集成与自定义

系列教程:这是《Google ADK 指南》系列的第五章。

前置知识:已完成第四章,掌握 Agent 开发。


目录

  1. 工具基础
  2. 内置工具
  3. 自定义工具开发
  4. [第三方 API 集成](#第三方 API 集成)
  5. [GCP 服务集成](#GCP 服务集成)
  6. 工具管理最佳实践

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": ""}  # 边界测试
])

系列教程导航

相关推荐
科技小花3 小时前
全球化深水区,数据治理成为企业出海 “核心竞争力”
大数据·数据库·人工智能·数据治理·数据中台·全球化
X56614 小时前
如何在 Laravel 中正确保存嵌套动态表单数据(主服务与子服务)
jvm·数据库·python
zhuiyisuifeng5 小时前
2026前瞻:GPTimage2镜像官网或将颠覆视觉创作
人工智能·gpt
徐健峰5 小时前
GPT-image-2 热门玩法实战(一):AI 看手相 — 一张手掌照片生成专业手相分析图
人工智能·gpt
weixin_370976355 小时前
AI的终极赛跑:进入AGI,还是泡沫破灭?
大数据·人工智能·agi
Slow菜鸟5 小时前
AI学习篇(五) | awesome-design-md 使用说明
人工智能·学习
运维开发王义杰5 小时前
DevOps Agent的自我进化:AI如何积累成功经验并形成程序性记忆?
agent
ZhengEnCi5 小时前
03ab-PyTorch安装教程 📚
python
冬奇Lab5 小时前
RAG 系列(五):Embedding 模型——语义理解的核心
人工智能·llm·aigc
深小乐5 小时前
AI 周刊【2026.04.27-05.03】:Anthropic 9000亿美元估值、英伟达死磕智能体、中央重磅定调AI
人工智能