Anthropic 在 Claude API 中引入了一个很重要的能力:Programmatic Tool Calling,程序化工具调用

很多人第一次看到这个概念会有点懵:
普通 Tool Calling 已经可以让模型调用工具了,为什么还需要“程序化”工具调用?

简单来说:

程序化工具调用,就是让 Claude 先写一段代码,然后在代码里批量、循环、条件式地调用工具,而不是每调用一次工具都重新让模型思考一轮。

它的核心价值是:减少模型与工具之间的反复往返,提高复杂 Agent 工作流的效率,降低 token 消耗,并减少上下文污染。


一、先理解普通 Tool Calling 的问题

传统 Tool Calling 的流程大概是这样:

用户提出任务
   ↓
模型判断要调用工具
   ↓
调用工具 A
   ↓
工具结果返回给模型
   ↓
模型继续思考
   ↓
调用工具 B
   ↓
工具结果返回给模型
   ↓
模型继续思考
   ↓
调用工具 C
   ↓
最终回答

这种方式在简单任务里没问题。

比如:

查一下今天东京天气

模型调用一次天气工具就结束了。

但如果任务变复杂,比如:

检查 20 个员工的报销是否超标

传统方式可能要:

查员工1 → 返回结果 → 模型判断
查员工2 → 返回结果 → 模型判断
查员工3 → 返回结果 → 模型判断
……
查员工20 → 返回结果 → 模型判断

这会带来几个问题:

  1. 延迟高:每次工具调用都要经过模型一轮推理。
  2. token 消耗高:每次工具结果都可能进入上下文。
  3. 上下文污染:大量中间数据塞进模型上下文,模型真正需要的可能只是最后的汇总结果。
  4. 复杂工作流不优雅:循环、过滤、排序、聚合这些事情,本来更适合代码来做,而不是每一步都让模型重新判断。

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 的程序化工具调用依赖两个东西:

  1. code_execution_20260120
  2. 工具上的 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 不只是会“调用工具”,而是会“写程序组织工具”。

Logo

欢迎加入DeepSeek 技术社区。在这里,你可以找到志同道合的朋友,共同探索AI技术的奥秘。

更多推荐