本文最后更新于 2026-05-11,文章内容可能已经过时。

Function Calling 完全指南:让 Claude 从"说话"变成"做事"

很多人学了一周 Function Calling,结果连 AI 有没有"真的执行"函数都搞不清楚。

这不怪你——大部分教程直接扔给你一堆代码,却没有解释清楚一件事:AI 在整个过程中,到底扮演了什么角色?

读完本文,你将能独立搭建一个可以调用外部工具的 AI 助手。我们从打破认知开始,到跑通第一个 Demo,再到处理并行多工具调用——循序渐进,每一步都有可以直接运行的代码。

---

第一章:你以为的 Function Calling vs 它实际在干什么

先问你一个问题:当你调用 Function Calling,AI 会"执行"你定义的函数吗?

不会。

这是最常见的误解。AI 模型本身是一个语言模型,它不能联网、不能读文件、不能调用你本地的任何代码。它能做的,是返回一个结构化的"意图信号",告诉你它想调用哪个函数、参数是什么——然后执行权完全交回给你。

用流程图对比一下:

【普通对话链路】

用户输入 → Claude 生成文本 → 返回给用户

(AI 全程只产出文字)

【Function Calling 链路】

用户输入

Claude 分析意图,判断"需要调用工具"

返回结构化信号:{"name": "get_weather", "input": {"city": "北京"}}

你的代码捕获这个信号,执行真实函数(调用天气 API)

把执行结果用 tool_result 格式回传给 Claude

Claude 读取结果,生成最终回答

返回给用户

(AI 只负责"决策",执行权始终在你手里)

理解这一点,你才真正入门了工具调用。

核心心智模型:Claude 是一个"决策者",不是"执行者"。Function Calling 的本质,是给 AI 一套"我能做什么"的工具说明书,让它在对话中自主决定何时、如何使用这些工具。

---

第二章:环境搭建 + 最小可运行示例

环境准备

pip install anthropic

你需要一个 Claude API Key。如果还没有,或者被访问限制困扰,可以直接通过 [api.884819.xyz](https://api.884819.xyz) 获取——国内直连,按量计费,新用户注册即送体验 token,几分钟内就能跑起来本文的第一个 Demo。

20 行最小 Demo

import anthropic

client = anthropic.Anthropic(api_key="your_api_key")

定义工具

tools = [

{

"name": "get_weather",

"description": "获取指定城市的实时天气信息",

"input_schema": {

"type": "object",

"properties": {

"city": {

"type": "string",

"description": "城市名称,例如:北京、上海"

}

},

"required": ["city"]

}

}

]

response = client.messages.create(

model="claude-opus-4-5",

max_tokens=1024,

tools=tools,

messages=[{"role": "user", "content": "北京今天天气怎么样?"}]

)

print(f"stop_reason: {response.stop_reason}")

print(f"content: {response.content}")

运行输出:
stop_reason: tool_use

content: [

TextBlock(text='我来帮您查询北京的天气。', type='text'),

ToolUseBlock(

id='toolu_01XYZ...',

name='get_weather',

input={'city': '北京'},

type='tool_use'

)

]

注意两个关键点:

1. stop_reason == "tool_use":这是 Claude 告诉你"我需要调用工具,请你去执行"的信号

2. ToolUseBlock:包含工具名称和参数,这就是你需要捕获并执行的"意图"

tools 参数的 JSON Schema 写法是新手最容易卡壳的地方。记住三要素:name(工具名)、description(功能描述,越清晰 AI 越准确)、input_schema(参数定义,遵循 JSON Schema 标准)。

---

第三章:3 个真实例子,从简单到复杂

例 1(简单):查实时天气 —— 单工具单轮调用

import anthropic

import json

client = anthropic.Anthropic(api_key="your_api_key")

tools = [

{

"name": "get_weather",

"description": "获取指定城市的实时天气",

"input_schema": {

"type": "object",

"properties": {

"city": {"type": "string", "description": "城市名称"}

},

"required": ["city"]

}

}

]

def get_weather(city: str) -> dict:

"""模拟天气 API 调用"""

weather_data = {

"北京": {"temp": 22, "condition": "晴", "humidity": 45},

"上海": {"temp": 28, "condition": "多云", "humidity": 72},

}

return weather_data.get(city, {"temp": 20, "condition": "未知", "humidity": 50})

def run_weather_query(user_message: str):

messages = [{"role": "user", "content": user_message}]

# 第一轮:让 Claude 决策

response = client.messages.create(

model="claude-opus-4-5",

max_tokens=1024,

tools=tools,

messages=messages

)

if response.stop_reason == "tool_use":

# 提取工具调用信息

tool_use_block = next(b for b in response.content if b.type == "tool_use")

tool_name = tool_use_block.name

tool_input = tool_use_block.input

# 执行工具

result = get_weather(tool_input["city"])

# 把结果回传给 Claude

messages.append({"role": "assistant", "content": response.content})

messages.append({

"role": "user",

"content": [{

"type": "tool_result",

"tool_use_id": tool_use_block.id,

"content": json.dumps(result, ensure_ascii=False)

}]

})

# 第二轮:Claude 生成最终回答

final_response = client.messages.create(

model="claude-opus-4-5",

max_tokens=1024,

tools=tools,

messages=messages

)

return final_response.content[0].text

return response.content[0].text

print(run_weather_query("北京今天天气怎么样?"))

运行输出:
北京今天天气晴朗,气温22°C,湿度45%,是个不错的天气!

恭喜,你已经掌握了 Function Calling 的基础闭环。

---

例 2(中等):联网搜索 + 摘要 —— 完整多轮链路

这个例子展示"AI 决策 → 工具执行 → 结果回传 → AI 再总结"的完整链路:

import anthropic

import json

client = anthropic.Anthropic(api_key="your_api_key")

tools = [

{

"name": "web_search",

"description": "搜索互联网获取最新信息,当需要实时数据或最新资讯时使用",

"input_schema": {

"type": "object",

"properties": {

"query": {"type": "string", "description": "搜索关键词"},

"max_results": {

"type": "integer",

"description": "返回结果数量,默认3",

"default": 3

}

},

"required": ["query"]

}

}

]

def web_search(query: str, max_results: int = 3) -> list:

"""模拟搜索 API"""

return [

{"title": f"关于'{query}'的最新报道", "snippet": f"这是关于{query}的详细信息...", "url": "https://example.com/1"},

{"title": f"{query}深度分析", "snippet": f"{query}的技术细节和应用场景...", "url": "https://example.com/2"},

][:max_results]

def run_search_and_summarize(user_message: str):

messages = [{"role": "user", "content": user_message}]

# 支持多轮工具调用

while True:

response = client.messages.create(

model="claude-opus-4-5",

max_tokens=2048,

tools=tools,

messages=messages

)

if response.stop_reason == "end_turn":

# AI 已经完成回答

return response.content[0].text

if response.stop_reason == "tool_use":

messages.append({"role": "assistant", "content": response.content})

# 处理所有工具调用

tool_results = []

for block in response.content:

if block.type == "tool_use":

if block.name == "web_search":

result = web_search(**block.input)

tool_results.append({

"type": "tool_result",

"tool_use_id": block.id,

"content": json.dumps(result, ensure_ascii=False)

})

messages.append({"role": "user", "content": tool_results})

print(run_search_and_summarize("帮我搜索一下 Claude Function Calling 的最新进展,并给我一个简洁的摘要"))

你已经掌握了多轮工具调用的完整链路。

---

例 3(进阶):并行工具调用 —— 同时查多个城市

根据 Anthropic 官方文档,Claude 支持在单次响应中返回多个 tool_use block,实现并行工具调用。这在需要同时获取多份数据时可以显著减少往返次数:

import anthropic

import json

from concurrent.futures import ThreadPoolExecutor

client = anthropic.Anthropic(api_key="your_api_key")

tools = [

{

"name": "get_weather",

"description": "获取指定城市的实时天气",

"input_schema": {

"type": "object",

"properties": {

"city": {"type": "string", "description": "城市名称"}

},

"required": ["city"]

}

}

]

def get_weather(city: str) -> dict:

weather_db = {

"北京": {"temp": 22, "condition": "晴"},

"上海": {"temp": 28, "condition": "多云"},

"广州": {"temp": 33, "condition": "阵雨"},

"成都": {"temp": 19, "condition": "阴"},

}

return weather_db.get(city, {"temp": 20, "condition": "未知"})

def run_parallel_weather(user_message: str):

messages = [{"role": "user", "content": user_message}]

response = client.messages.create(

model="claude-opus-4-5",

max_tokens=1024,

tools=tools,

messages=messages

)

if response.stop_reason == "tool_use":

messages.append({"role": "assistant", "content": response.content})

# 提取所有工具调用

tool_use_blocks = [b for b in response.content if b.type == "tool_use"]

print(f"Claude 同时发起了 {len(tool_use_blocks)} 个工具调用")

# 并行执行(这里用线程池模拟)

def execute_tool(block):

result = get_weather(block.input["city"])

return {

"type": "tool_result",

"tool_use_id": block.id,

"content": json.dumps(result, ensure_ascii=False)

}

with ThreadPoolExecutor() as executor:

tool_results = list(executor.map(execute_tool, tool_use_blocks))

messages.append({"role": "user", "content": tool_results})

final_response = client.messages.create(

model="claude-opus-4-5",

max_tokens=1024,

tools=tools,

messages=messages

)

return final_response.content[0].text

result = run_parallel_weather("帮我同时查一下北京、上海、广州、成都今天的天气,做个对比")

print(result)

运行输出:
Claude 同时发起了 4 个工具调用

今日四城天气对比:

  • 北京:22°C,晴,适合出行
  • 上海:28°C,多云,较为闷热
  • 广州:33°C,阵雨,记得带伞
  • 成都:19°C,阴,气温舒适

你现在已经掌握了并行工具调用——这是构建高效 Agent 的关键技术。

---

第四章:3 个新手必踩的坑

坑 1:忘记回传 tool_result,对话直接卡死

错误代码:
# ❌ 错误:拿到工具调用结果后,忘记回传

if response.stop_reason == "tool_use":

result = get_weather("北京")

# 直接打印,没有回传给 Claude

print(result)

报错现象: Claude 停在工具调用阶段,永远不生成最终回答,或者你的循环逻辑陷入死循环。 修复方案:
# ✅ 正确:必须把结果用 tool_result 格式回传

if response.stop_reason == "tool_use":

messages.append({"role": "assistant", "content": response.content})

messages.append({

"role": "user",

"content": [{

"type": "tool_result",

"tool_use_id": tool_use_block.id, # 必须对应原始调用的 id

"content": json.dumps(result)

}]

})

这个坑我当年踩了两个小时,现在省给你。

---

坑 2:JSON Schema 写得不够精确,AI 乱填参数

错误代码:
# ❌ 错误:description 太模糊,没有 required 字段

{

"name": "get_weather",

"description": "天气",

"input_schema": {

"type": "object",

"properties": {

"city": {"type": "string"}

}

# 缺少 required!

}

}

报错现象: Claude 可能不传 city 参数,或者传入格式错误的值(比如传 "北京市朝阳区" 而不是 "北京")。 修复方案:
# ✅ 正确:description 清晰,required 完整,加上 enum 约束

{

"name": "get_weather",

"description": "获取指定城市的实时天气信息。city 参数必须是城市名,不含区县",

"input_schema": {

"type": "object",

"properties": {

"city": {

"type": "string",

"description": "城市名称,例如:北京、上海、广州"

}

},

"required": ["city"]

}

}

原则description 写给 AI 看,越具体越好。你对工具的描述质量,直接决定 AI 调用的准确率。

---

坑 3:没处理 end_turn,循环逻辑写错

错误代码:
# ❌ 错误:只处理了 tool_use,忘记处理 end_turn

while True:

response = client.messages.create(...)

if response.stop_reason == "tool_use":

# 处理工具调用

...

# 没有 end_turn 的退出条件 → 无限循环!

报错现象: 程序无限循环,API 调用次数暴增,账单飞涨。 修复方案:
# ✅ 正确:完整处理所有 stop_reason

while True:

response = client.messages.create(...)

if response.stop_reason == "end_turn":

return response.content[0].text # 正常结束

if response.stop_reason == "tool_use":

# 处理工具调用,继续循环

...

# 兜底处理其他情况

else:

break

---

第五章:何时用 Function Calling,何时不用

不是所有场景都需要工具调用。引入它会增加代码复杂度和 API 调用次数,用错地方反而是负担。

| 场景 | 是否用 Function Calling | 原因 | | 查实时天气/股价 | ✅ 用 | 需要实时数据,模型知识有截止日期 | | 操作数据库/文件系统 | ✅ 用 | 需要与外部系统交互 | | 生成结构化 JSON 输出 | ✅ 用 | 工具调用天然返回结构化数据 | | 写一篇文章/代码 | ❌ 不用 | 纯文本生成,模型直接完成 | | 回答知识性问题 | ❌ 不用 | 模型自身知识足够,无需外部数据 | | 简单的数学计算 | ❌ 不用(通常) | 模型直接推理,除非精度要求极高 | | 多步骤自动化任务 | ✅ 用 | 这就是 Agent 的核心场景 | 判断原则很简单:问自己一个问题——"这个任务需要 AI 知道它自己不知道的东西吗?" 如果答案是肯定的(实时数据、外部系统状态、用户私有数据),就用工具调用。

---

结语

Function Calling 不是一个"高级功能",它是 AI 从"聊天机器人"进化到"自动化 Agent"的关键一步。

你刚刚学会的,是让 AI 从"说话"变成"做事"的核心技术。

文中所有代码在标准 Claude API 环境下均已测试通过。API 获取及用量管理:[api.884819.xyz](https://api.884819.xyz),国产模型完全免费,无月租,按量付费。

---

🔮 下一篇预告

>

工具调用你已经会了。

>

但如果工具不止一个、对话不止一轮、AI 需要自己决定"下一步做什么"——
那就不叫工具调用,叫 Agent

>

下一篇,我们用 Claude 从零搭一个能自主完成任务的 AI Agent,看看它和今天这些例子,差在哪里。

>

关注 8848AI,不要错过。

---

本文由8848AI原创,转载请注明出处。关注8848AI,带你从零开始学AI。

#AI教程 #FunctionCalling #Claude #AI开发 #Python #AIAgent #8848AI #工具调用