📖 什么是 Tool Calling?
凌晨2点15分,我和一个Agent聊天。我问他"帮我查一下今天的比特币价格",他开始了一堆"我在思考如何查询比特币价格,这是一个涉及加密货币市场的复杂问题..."——我当场崩溃!
这就是没有Tool Calling的Agent:它知道怎么查,但它没有手去查!
Tool Calling(也叫 Function Calling) 就是给AI模型"一双手"——让它不仅能"思考",还能"行动"。具体来说:
- 🤔 以前:AI只能写文字告诉你"建议你用API查",然后你手动查
- 🖐️ 现在:AI可以直接调用你定义好的工具/API,获取结果后给你答案
- 🚀 结果:AI从"聊天机器人"进化成了"能干活的人"
🧠 工作原理
核心流程
Tool Calling的工作流程就像外卖点餐:
# Tool Calling 的完整流程
## Step 1: 定义工具(JSON Schema格式)
tools = [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "获取指定城市的天气信息",
"parameters": {
"type": "object",
"properties": {
"city": {"type": "string", "description": "城市名"}
},
"required": ["city"]
}
}
}
]
## Step 2: 用户发出请求
"北京今天天气怎么样?"
## Step 3: AI模型返回工具调用指令
{
"tool_calls": [
{
"id": "call_abc123",
"type": "function",
"function": {
"name": "get_weather",
"arguments": "{\"city\": \"北京\"}"
}
}
]
}
## Step 4: 执行工具函数
result = get_weather(city="北京")
# 返回: {"temperature": 28, "condition": "多云"}
## Step 5: 将结果返回给AI
messages.append({
"role": "tool",
"tool_call_id": "call_abc123",
"content": json.dumps(result)
})
## Step 6: AI生成最终回复
"北京今天天气:多云,28°C。非常适合出门逛街!"
关键概念对比
Function Calling
OpenAI最早提出的概念,让模型返回结构化函数调用参数
特点: 单轮调用、一次性
Tool Calling
广义概念,包括所有形式的工具调用(函数、插件、API等)
特点: 支持多轮、多工具
MCP Tool
标准化的工具调用协议
特点: 跨平台、标准化
🛠️ OpenClaw 中的 Tool Calling
OpenClaw内置工具一览
📝 write / read
文件读写工具,用于处理各种文件
💻 exec
执行系统命令,支持各种CLI工具
🌐 web_search
搜索网络信息,获取实时数据
📄 web_fetch
爬取网页内容,提取有用信息
🌐 browser
浏览器自动化,处理Web交互
⏰ cron
定时任务管理,调度自动化流程
📧 message
发送消息通知到各种渠道
💾 feishu_*
飞书生态集成(文档、表格、群聊等)
场景1: 多工具协作完成复杂任务
# 用户请求:"帮我生成一篇关于WebSocket的文章并发布到网站"
# OpenClaw内部多工具调用流程
┌─────────────────────────────────────────────────┐
│ 1. web_search("WebSocket 教程 最佳实践 2026") │
│ → 获取相关资料 │
├─────────────────────────────────────────────────┤
│ 2. web_fetch("https://example.com/ws-guide") │
│ → 抓取详细内容 │
├─────────────────────────────────────────────────┤
│ 3. write("/var/www/miaoquai/articles/ │
│ websocket-guide.html", html_content) │
│ → 保存页面 │
├─────────────────────────────────────────────────┤
│ 4. exec("curl -I https://miaoquai.com/...") │
│ → 验证页面可访问 (200 OK) │
├─────────────────────────────────────────────────┤
│ 5. message(text="新页面: websocket-guide ✅") │
│ → 发送通知到飞书 │
└─────────────────────────────────────────────────┘
场景2: 智能体主导的多轮工具调用
OpenClaw智能体会自动判断何时需要调用工具,完成复杂的多步任务:
# 用户:"帮我分析一下今天AI行业的重大新闻"
# Agent 自动执行以下工具调用链:
# 第1轮:搜索
tools_call_1: web_search("AI news today {current_date}")
result_1: [{"title": "GPT-5发布...", "url": "..."}, ...]
# 第2轮:逐个抓取详情
for each in result_1[:5]:
tools_call_N: web_fetch(each.url)
# 第3轮:生成总结
write("/var/www/miaoquai/news/{date}.html", summary)
# 第4轮:通知
message("今日AI日报已生成 → https://miaoquai.com/news/{date}.html")
🧰 工具定义最佳实践
1. 清晰的Tool Description
工具描述直接影响AI能否正确使用它:
# ❌ 不好的描述 "获取文件" — AI可能不知道是用来读还是写 # ✅ 好的描述 "读取指定路径的文件内容,返回纯文本。 注意:只能读取 /var/www/miaoquai/ 目录下的文件 遇到权限错误时返回友好的错误提示"
2. 参数设计原则
- 参数名要有意义 - `path` 比 `p` 好一万倍
- 提供枚举值 - 如果参数只有几个选项,列出它们
- 设置默认值 - 减少AI的决策负担
- 详细描述 - 每个参数都说明"这是什么"和"什么格式"
- required标记明确 - 哪些必须,哪些可选
3. 错误处理模式
# 工具执行失败时的处理策略
def smart_tool_wrapper(func):
def wrapper(*args, **kwargs):
try:
result = func(*args, **kwargs)
return {"success": True, "data": result}
except FileNotFoundError:
return {"success": False, "error": "文件不存在"}
except PermissionError:
return {"success": False, "error": "权限不足"}
except Exception as e:
return {"success": False, "error": f"未知错误: {str(e)}"}
return wrapper
📊 性能与注意事项
⏱️ 延迟影响
每次Tool Calling增加200-500ms延迟,合理规划调用次数
💰 Token成本
Tools定义会占用大量token(尤其是JSON Schema),注意预算
🔄 调用限制
OpenAI等模型有max_tool_calls限制,超量会被截断
🔐 安全考量
工具调用可能成为攻击面,严格控制权限和输入验证