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

系列教程导航

相关推荐
智算菩萨2 小时前
【Generative AI For Autonomous Driving】1 生成式AI重塑自动驾驶的技术浪潮与体系化挑战
论文阅读·人工智能·深度学习·机器学习·ai·自动驾驶
故事和你912 小时前
sdut-python-实验四-python序列结构(21-27)
大数据·开发语言·数据结构·python·算法
程序员Better2 小时前
一口气拆穿Skill/MCP/RAG/Agent/OpenClaw底层逻辑
人工智能·开源·agent
chushiyunen2 小时前
pycharm注意力残差示例
ide·python·pycharm
智算菩萨2 小时前
【Generative AI For Autonomous Driving】7 生成式AI驱动自动驾驶的未来图景:开放挑战、社会机遇与技术展望
论文阅读·人工智能·深度学习·机器学习·ai·自动驾驶
2301_793804692 小时前
用Python和Twilio构建短信通知系统
jvm·数据库·python
B站_计算机毕业设计之家2 小时前
计算机毕业设计:Python当当网图书数据全链路处理平台 Django框架 爬虫 Pandas 可视化 大数据 大模型 书籍(建议收藏)✅
爬虫·python·机器学习·django·flask·pandas·课程设计
_Twink1e2 小时前
2023-2026年计算机视觉领域期刊整理汇总
人工智能·计算机视觉
AI英德西牛仔2 小时前
deepseek怎么导出文档
人工智能·ai·chatgpt·deepseek·ds随心转