Anthropic 程序化工具调用是什么?有什么用?解决了什么问题?
Anthropic 在 Claude API 中引入了一个很重要的能力:Programmatic Tool Calling,程序化工具调用。
很多人第一次看到这个概念会有点懵:
普通 Tool Calling 已经可以让模型调用工具了,为什么还需要“程序化”工具调用?
简单来说:
程序化工具调用,就是让 Claude 先写一段代码,然后在代码里批量、循环、条件式地调用工具,而不是每调用一次工具都重新让模型思考一轮。
它的核心价值是:减少模型与工具之间的反复往返,提高复杂 Agent 工作流的效率,降低 token 消耗,并减少上下文污染。
一、先理解普通 Tool Calling 的问题
传统 Tool Calling 的流程大概是这样:
用户提出任务
↓
模型判断要调用工具
↓
调用工具 A
↓
工具结果返回给模型
↓
模型继续思考
↓
调用工具 B
↓
工具结果返回给模型
↓
模型继续思考
↓
调用工具 C
↓
最终回答
这种方式在简单任务里没问题。
比如:
查一下今天东京天气
模型调用一次天气工具就结束了。
但如果任务变复杂,比如:
检查 20 个员工的报销是否超标
传统方式可能要:
查员工1 → 返回结果 → 模型判断
查员工2 → 返回结果 → 模型判断
查员工3 → 返回结果 → 模型判断
……
查员工20 → 返回结果 → 模型判断
这会带来几个问题:
- 延迟高:每次工具调用都要经过模型一轮推理。
- token 消耗高:每次工具结果都可能进入上下文。
- 上下文污染:大量中间数据塞进模型上下文,模型真正需要的可能只是最后的汇总结果。
- 复杂工作流不优雅:循环、过滤、排序、聚合这些事情,本来更适合代码来做,而不是每一步都让模型重新判断。
Anthropic 的程序化工具调用就是为了解决这个问题。
二、什么是程序化工具调用?
程序化工具调用可以理解为:
Claude 可以在代码执行环境中,把开发者定义的工具当作函数来调用。
也就是说,Claude 不只是“直接调用工具”,而是可以先写一段 Python 代码,然后在代码里面这样调用工具:
regions = ["West", "East", "Central"]
results = {}
for region in regions:
data = await query_database(f"SELECT * FROM sales WHERE region = '{region}'")
results[region] = sum(row["revenue"] for row in data)
print(max(results, key=results.get))
这里的 query_database 就是开发者提供的工具。
以前模型可能需要三次工具调用:
查 West
查 East
查 Central
现在 Claude 可以写一段代码,用循环一次性完成。
Anthropic 官方文档中提到,程序化工具调用允许 Claude 在代码执行容器中以编程方式调用工具,从而减少多工具工作流中的延迟和 token 消耗。
三、它和普通 Tool Calling 的区别
| 对比项 | 普通 Tool Calling | 程序化 Tool Calling |
|---|---|---|
| 调用方式 | 模型直接调用工具 | 模型写代码,代码调用工具 |
| 适合场景 | 单次查询、简单工具调用 | 多步骤、批量、循环、聚合任务 |
| 中间结果 | 通常返回给模型上下文 | 可以在代码里先处理,只返回最终摘要 |
| token 消耗 | 较高 | 更低 |
| 延迟 | 多轮调用时较高 | 多个工具调用可以放在一次代码执行中 |
| 工作流能力 | 依赖模型逐步推理 | 可以使用循环、条件、排序、过滤等编程逻辑 |
一句话总结:
普通 Tool Calling 是“模型一步一步调用工具”;程序化工具调用是“模型写代码,让代码批量调用工具”。
四、它的核心机制是什么?
Anthropic 的程序化工具调用依赖两个东西:
code_execution_20260120- 工具上的
allowed_callers
示例:
{
"type": "code_execution_20260120",
"name": "code_execution"
}
这是 Claude 的代码执行工具。
然后你定义自己的业务工具,比如:
{
"name": "query_database",
"description": "Execute a SQL query against the sales database.",
"input_schema": {
"type": "object",
"properties": {
"sql": {
"type": "string",
"description": "SQL query to execute"
}
},
"required": ["sql"]
},
"allowed_callers": ["code_execution_20260120"]
}
关键是这一行:
"allowed_callers": ["code_execution_20260120"]
它表示:
这个工具允许被 Claude 的代码执行环境调用。
也就是说,Claude 可以在它写的 Python 代码里这样用:
result = await query_database("SELECT * FROM sales")
五、Anthropic 是怎么调用本地工具的?
这里很容易误解。
很多人会以为:
Anthropic 的云端容器直接访问我的本地工具
其实不是。
Anthropic 不会主动访问你的本地环境。
真实流程是:
1. Claude 在 Anthropic 沙箱里执行代码
2. 代码运行到:
await query_database(...)
3. Anthropic 暂停代码执行,返回一个 tool_use 请求给你的客户端程序
4. 你的客户端程序在本地执行 query_database
5. 你的客户端程序把 tool_result 发回 Anthropic
6. Anthropic 沙箱里的代码继续运行
所以 Anthropic 并不是直接请求你的 localhost,而是通过 API 的 tool_use / tool_result 协议完成“远程函数调用”。
可以理解为:
Anthropic:我需要调用 query_database,参数是 {...}
你的程序:好的,我本地执行完了,结果是 {...}
Anthropic:收到,继续执行代码
六、它解决了什么问题?
1. 解决多工具调用延迟高的问题
假设要检查 50 个服务器的健康状态。
普通 Tool Calling 可能是:
模型调用 check_health(server1)
模型收到结果
模型调用 check_health(server2)
模型收到结果
……
程序化工具调用可以是:
servers = ["server1", "server2", "server3"]
for server in servers:
status = await check_health(server)
if status == "unhealthy":
print(server)
这样模型不用每检查一个服务器就重新推理一轮。
2. 解决 token 消耗过高的问题
如果工具返回大量数据,普通 Tool Calling 可能会把原始结果全部塞进上下文。
比如数据库返回 10,000 行数据,模型其实只需要 Top 5。
程序化工具调用可以先在代码里处理:
rows = await query_database(sql)
top_5 = sorted(rows, key=lambda x: x["revenue"], reverse=True)[:5]
print(top_5)
模型最后只看到 top_5,而不是完整的 10,000 行。
这可以显著减少 token 消耗。
3. 解决上下文污染问题
大模型的上下文窗口虽然越来越大,但不是所有数据都应该进入上下文。
有些数据只是中间过程,比如:
原始日志
数据库中间结果
大量候选文件
批量 API 返回结果
这些内容如果都进入模型上下文,会干扰模型判断。
程序化工具调用允许 Claude 在代码中先做过滤、排序、聚合,只把必要结果返回给模型。
4. 解决复杂 Agent 工作流难编排的问题
很多 Agent 任务天然适合编程逻辑:
读取文件
判断文件大小
小文件读全文
大文件读摘要
提取关键信息
写入数据库
检查一致性
输出报告
如果完全靠普通 Tool Calling,流程会比较笨重。
程序化工具调用可以把这些逻辑写成代码:
files = await list_files()
for file in files:
info = await get_file_info(file["path"])
if info["size"] < 10000:
content = await read_full_file(file["path"])
else:
content = await read_file_summary(file["path"])
result = await extract_key_info(content)
print(result)
这样 Agent 的能力会更接近一个真正会编程的自动化助手。
七、适合哪些场景?
程序化工具调用特别适合这些场景:
1. 批量数据处理
比如:
检查 100 个订单
分析 50 个客户
查询多个地区销售额
批量读取多份文件
2. 多步骤工具链
比如:
搜索文件 → 读取文件 → 提取信息 → 写入数据库 → 生成报告
3. 需要过滤、排序、聚合的任务
比如:
从 1000 条日志里找最近 10 条错误
从数据库里找销售额最高的 5 个客户
从多个结果中筛选符合条件的记录
4. Agent 系统
比如:
代码 Agent
数据分析 Agent
知识库 Agent
Text-to-SQL Agent
自动化办公 Agent
知识图谱 Agent
尤其是复杂 Agent,如果每一步都让模型重新思考,会很慢、很贵,也不稳定。
程序化工具调用可以让模型把“流程控制”交给代码。
八、和知识图谱 Agent 的关系
比如你要做一个小说创作知识图谱系统。
每写完一章,需要:
读取章节
抽取实体
抽取关系
写入 Neo4j
检查人物关系冲突
检查时间线冲突
检查战力设定冲突
更新账本
用程序化工具调用,可以设计这些工具:
read_chapter
extract_entities
extract_relations
query_neo4j
write_neo4j
check_consistency
update_ledger
Claude 可以写代码统一调度:
chapters = await read_recent_chapters(count=10)
for chapter in chapters:
entities = await extract_entities(chapter["content"])
relations = await extract_relations(chapter["content"])
await write_neo4j({
"entities": entities,
"relations": relations
})
conflicts = await check_consistency()
print(conflicts)
这样就不是每一章、每一步都靠模型来回判断,而是让代码负责流程,让模型负责理解和决策。
九、它不是万能的
程序化工具调用虽然很强,但也不是所有场景都适合。
不太适合的场景包括:
只需要调用一次工具
工具结果很短
任务不需要循环、过滤、聚合
需要模型实时根据每个中间结果进行复杂判断
比如:
查一下今天的天气
这种任务直接普通 Tool Calling 就可以。
没必要为了一个简单工具调用启动代码执行环境。
十、需要注意的限制
1. 需要启用 Code Execution
Anthropic 文档中说明,程序化工具调用需要启用代码执行工具。
2. 工具需要声明 allowed_callers
你的工具必须声明:
"allowed_callers": ["code_execution_20260120"]
否则 Claude 的代码执行环境不能调用它。
3. Anthropic 不会直接访问本地工具
你的本地服务需要实现工具分发器。
也就是说,当 API 返回 tool_use 时,你的程序要根据工具名执行对应函数:
if tool_name == "query_neo4j":
result = query_neo4j(**tool_input)
然后把结果作为 tool_result 回传。
4. 不能盲目执行模型生成的代码
如果你自己实现本地代码执行器,不要直接在主机上 exec 模型生成的代码。
应该使用:
Docker
沙箱
权限隔离
超时限制
文件系统隔离
网络限制
否则会有安全风险。
十一、一个简单比喻
普通 Tool Calling 像这样:
老板每做一步都亲自问员工:
你查一下 A
你查一下 B
你查一下 C
然后老板自己汇总
程序化工具调用像这样:
老板写了一张流程表:
把 A、B、C 都查了
过滤掉无效数据
按金额排序
只把前 5 个结果给我
也就是说,Claude 不再只是“一个会调用工具的模型”,而更像是“一个能写自动化脚本来调度工具的 Agent”。
十二、总结
Anthropic 的程序化工具调用,本质上是:
让 Claude 在代码执行环境里,以编程方式调用开发者提供的工具。
它主要解决了四个问题:
1. 多工具调用延迟高
2. 中间结果 token 消耗大
3. 大量原始数据污染上下文
4. 复杂 Agent 工作流难以高效编排
它最适合:
批量处理
多步骤 Agent
大数据过滤聚合
自动化工具链
知识库 / 数据库 / 知识图谱工作流
一句话概括:
普通 Tool Calling 是让模型一步步调用工具;程序化工具调用是让模型写代码来批量调度工具。
这代表 Agent 架构的一个重要方向:
未来的强 Agent 不只是会“调用工具”,而是会“写程序组织工具”。
更多推荐



所有评论(0)