🔧 Agent Tool Calling 最佳实践
让AI真正为你工作:从工具设计到性能优化
TL;DR:Tool Calling是Agent的核心能力,决定了AI能否真正执行任务。本文涵盖工具设计原则、参数优化、错误处理、调用模式等实战技巧,助你构建生产级Agent。
🎯 什么是 Tool Calling?
Tool Calling(工具调用)是LLM与外部世界交互的核心能力。通过定义工具,Agent可以:
- 获取实时信息:搜索、查询API、读取数据库
- 执行操作:发送消息、创建文件、调用服务
- 访问工具:使用计算器、代码执行、文件处理
💡 核心概念:Tool Calling不是"调用函数",而是让LLM理解何时、如何调用外部能力完成复杂任务。
🛠️ 工具设计原则
1. 单一职责原则
每个工具只做一件事,且做到最好:
# ✅ 好的设计:单一功能
def search_web(query: str) -> list:
"""搜索互联网获取最新信息"""
...
def send_email(to: str, subject: str, body: str) -> dict:
"""发送电子邮件"""
...
# ❌ 避免:功能堆砌
def do_everything(query: str, action: str, **kwargs) -> any:
"""搜索、发送邮件、处理文件..."""
...
2. 清晰的描述文档
工具描述是LLM理解工具用途的唯一来源:
# ✅ 优秀的工具描述
def create_calendar_event(
title: str,
start_time: str,
end_time: str,
attendees: list = None,
location: str = None,
description: str = None
) -> dict:
"""
创建日历事件
参数:
- title: 事件标题,必填,简洁明确,如"团队周会"
- start_time: 开始时间,ISO 8601格式,必填,如"2026-07-09T10:00:00+08:00"
- end_time: 结束时间,ISO 8601格式,必填
- attendees: 参会人邮箱列表,可选
- location: 会议地点,可选
- description: 事件描述,可选
返回:
包含event_id的成功响应,或错误信息
注意: 时间必须使用东八区(Asia/Shanghai)时区
"""
...
📋 参数优化技巧
1. 使用 Enum 限制取值
当参数有固定取值时,使用枚举限制范围:
from enum import Enum
class Priority(Enum):
LOW = "low"
MEDIUM = "medium"
HIGH = "high"
URGENT = "urgent"
class TaskStatus(Enum):
PENDING = "pending"
IN_PROGRESS = "in_progress"
COMPLETED = "completed"
CANCELLED = "cancelled"
# LLM会更准确地选择正确值
2. 必填 vs 可选参数
| 参数类型 | 处理方式 | 示例 |
| 必填 | 无默认值,描述中强调 | title: str (会议标题) |
| 可选 | 有默认值,描述默认值 | reminder_minutes: int = 15 |
| 条件必填 | 在描述中说明触发条件 | 当action=delete时,id必填 |
🔄 错误处理模式
1. 重试机制
import time
from functools import wraps
def retry(max_attempts=3, delay=1, backoff=2):
"""指数退避重试装饰器"""
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
attempts = 0
current_delay = delay
while attempts < max_attempts:
try:
return func(*args, **kwargs)
except Exception as e:
attempts += 1
if attempts >= max_attempts:
raise e
time.sleep(current_delay)
current_delay *= backoff
return None
return wrapper
return decorator
@retry(max_attempts=3, delay=1)
def call_api_with_retry(params):
"""带重试的API调用"""
...
2. 优雅降级
⚠️ 重要:当工具不可用时,Agent应能优雅降级,而不是直接失败。提供fallback方案或明确告知用户。
⚡ 性能优化
1. 并行调用
独立工具可以并行调用:
import asyncio
async def parallel_tool_calls(tools):
"""并行执行多个独立工具调用"""
tasks = [tool.execute() for tool in tools]
results = await asyncio.gather(*tasks, return_exceptions=True)
return results
# 示例:同时获取天气和新闻
weather_task = get_weather("北京")
news_task = get_latest_news()
weather, news = await asyncio.gather(weather_task, news_task)
2. 缓存策略
from functools import lru_cache
@lru_cache(maxsize=128)
def cached_search(query: str) -> list:
"""缓存搜索结果,避免重复调用"""
# 实际搜索逻辑
return search_api(query)
🧪 最佳实践清单
- ✅ 工具命名清晰:使用动词+名词,如send_email、create_task
- ✅ 描述完整:说明参数、返回值、注意事项
- ✅ 参数类型明确:使用Type Hint,优先使用Enum
- ✅ 错误处理完善:重试、降级、清晰错误信息
- ✅ 日志记录:记录每次调用,便于调试和审计
- ✅ 权限控制:最小权限原则,避免过度授权
- ✅ 超时设置:为每个工具设置合理超时时间
🔗 相关资源
Tool Calling
Agent开发
LLM
最佳实践