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

系列教程导航

相关推荐
a11177644 分钟前
SLAM 学习笔记(三)视觉里程计2(VO) 特征点法
人工智能·笔记·学习
湘美书院--湘美谈教育1 小时前
湘美谈教育湘美书院绥宁文学系列:AI时代的小说,雪峰号
大数据·人工智能·深度学习·机器学习·生活
汤姆yu1 小时前
面向具身智能的物理视频模拟器:蚂蚁灵波LingBot-Video开源模型全解析
java·大数据·人工智能·gpt·开源·大模型·音视频
三品吉他手会点灯1 小时前
嵌入式机器学习 - 学习笔记1.1.2 - 机器学习的局限性与伦理
人工智能·笔记·嵌入式硬件·学习·机器学习
Xpower 171 小时前
详细解释 Codex 最近一次功能更新,以及 GPT-5.6 Sol、Terra、Luna 的能力、价格、使用方式和适用场景。
人工智能·python·gpt·学习
技术小黑1 小时前
RNN算法实战系列02 | 医疗成本预测(LSTM 回归)
人工智能·pytorch·rnn·深度学习·lstm
龙腾AI白云1 小时前
【多Agent系统的倒U型曲线与前瞻治理】
人工智能·plotly·pyqt·知识图谱
一枚NPC1 小时前
Timbal AI 音乐创作与商业应用实战指南
大数据·人工智能·机器学习
Daorigin_com1 小时前
合同管理进入“自动驾驶”时代:道本×DeepSeek的三重穿透
大数据·人工智能·深度学习·数据挖掘·数据库开发·业界资讯·改行学it
xcLeigh1 小时前
Token 与上下文窗口:理解 AI 模型的「记忆」与限制
人工智能·ai·ai编程