摘要

1) 一句话总结 编程式工具调用 (PTC) 允许 Claude 在代码执行环境中以编程方式调用工具,通过在代码层面处理复杂数据和顺序逻辑,显著降低 Token 消耗并优化多步工具调用的效率。

2) 核心要点

  • 工作原理:PTC 允许 Claude 编写代码并在代码执行环境中调用工具,避免了每次工具调用都必须与模型进行往返交互。
  • 显著降低 Token 消耗:通过在代码环境中直接解析、过滤和汇总庞大且富含元数据的数据集,避免将无关上下文传入模型窗口。在费用分析实战案例中,PTC 将 Token 使用量减少了 85.6%(从 110,473 降至 15,919)。
  • 优化顺序依赖:对于需要基于前置结果进行后续调用的场景,PTC 可以在代码中通过循环和状态保持来编排整个工作流,将多次顺序 API 往返转化为更智能的编排。
  • 计算逻辑卸载:将算术和聚合逻辑委托给 Python 代码执行,减轻了模型的认知负荷,确保了计算精度,并防止原始数据污染模型上下文。
  • 工具权限配置:必须在工具定义中显式添加 allowed_callers 字段(例如包含 "code_execution_20250825"),否则工具默认只能由模型直接调用。
  • API 调用要求:需要使用 Beta 版本的 Messages API(在请求头中添加 "advanced-tool-use-2025-11-20"),对于有状态工作流需传入 container_id
  • 环境依赖:要求使用 Python 3.11 或更高版本,以及 Anthropic Python SDK >= 0.72。

3) 风险/限制

  • 执行安全风险:由于代码执行环境中的工具调用缺乏人工监督,必须仅为那些对于编程式或重复执行绝对安全的工具启用 PTC。
  • API 调用次数可能不减:由于 PTC 倾向于编写结构化、遵循最佳实践的顺序代码(例如将获取数据与检查逻辑分开),它可能不会减少 API 的总调用次数(案例中传统方式与 PTC 均为 4 次调用),其核心优势在于 Token 效率而非调用频次。

正文

使用 Claude API 的编程式工具调用 (PTC)

编程式工具调用 (Programmatic Tool Calling, PTC) 允许 Claude 编写代码,在代码执行环境 (Code Execution environment) 中以编程方式调用工具,而无需为每次工具调用在模型之间进行往返交互。这大幅降低了多次工具调用的端到端延迟,并且通过允许模型编写代码在无关上下文进入模型上下文窗口之前将其移除(例如,通过在庞大且嘈杂的文件中检索关键信息),可以显著减少 Token 消耗。

当面临您可能无法直接修改的第三方 API 和工具时,PTC 可以允许 Claude 编写能在代码执行环境中调用的代码,从而帮助减少上下文的使用。

在本实战教程 (cookbook) 中,我们将使用一个用于团队费用管理的模拟 API。该 API 被设计为需要多次调用,并会返回大量结果,这有助于说明编程式工具调用的优势。

学完本教程后,您将能够:

  • 理解常规工具调用与编程式工具调用 (PTC) 之间的区别
  • 编写利用 PTC 的智能体 (agents)

前置条件

在按照本指南操作之前,请确保您具备:

必备知识

  • Python 基础 - 熟练掌握 async/await、函数和基本数据结构
  • 对智能体模式 (agentic patterns) 和工具调用的基本理解

必备工具

  • Python 3.11 或更高版本
  • Anthropic API 密钥
  • Anthropic Python SDK >= 0.72

设置

首先,安装所需的依赖项:

注意:请确保您的 .env 文件包含:

ANTHROPIC_API_KEY=your_key_here

加载您的环境变量并配置客户端。我们还加载了一个辅助工具来可视化 Claude 的消息响应。

了解第三方 API

tool_use/utils/team_expense_api.py 中,定义了三个函数:get_team_membersget_expensesget_custom_budgetget_team_members 函数允许我们检索给定部门中的所有员工及其角色、级别和联系信息。get_expenses 函数返回特定季度某位员工的所有费用明细——每位员工可能有数百条记录,每条记录包含大量元数据,包括收据 URL、审批链、商户详细信息等。get_custom_budget 函数检查特定员工是否有自定义的差旅预算例外(否则他们将使用标准的 5,000 美元季度额度)。

在这个场景中,我们需要分析团队费用并找出哪些员工超出了预算。传统上,我们可能会手动提取每个人的费用报告,按类别汇总他们的费用,与预算限额进行比较(检查自定义预算例外),然后编制一份报告。相反,我们将要求 Claude 为我们执行此分析,使用可用的工具检索团队数据,获取可能包含丰富元数据的数百条费用明细,并确定谁超出了预算。

这里的主要挑战是,每位员工可能有 100 多条费用明细需要获取、解析和汇总——而且 get_custom_budget 工具只能在分析费用以查看是否有人超出标准预算后才能调用。这创建了一个顺序依赖链,使其成为展示编程式工具调用优势的理想用例。

我们将把工具定义传递给 messages API,并要求 Claude 执行分析。如果您不熟悉工具调用在 Claude API 中的工作原理,请阅读关于实现工具调用 (implementing tool use) 的文档。

传统工具调用(基准)

在第一个示例中,我们将使用传统的工具调用来建立我们的基准。

我们将使用初始查询调用 messages.create API。当模型以 tool_use 原因停止时,我们将按要求执行工具,然后将工具的输出添加到消息中并再次调用模型。

我们向模型发出的初始查询提供了一些指令来帮助引导模型。为了简洁起见,我们要求模型只调用每个工具一次。对于更深入的调查,模型可能希望查看多个系统或时间跨度。

╭────────────────────────────────────────────── Claude API 响应 ──────────────────────────────────────────────╮ │ Claude 消息 (assistant) │ tokens: 输入 1,859 • 输出 85 • 总计 1,944 │ │ ├── 模型: claude-sonnet-4-6 │ │ ├── 停止原因: tool_use │ │ └── 内容 (2 个块) │ │ ├── 块 1 │ │ │ └── 文本 │ │ │ └── 我将帮您找出哪些工程团队成员超出了他们的第三季度差旅预算。让我先获取工程团队成员的列表。 │ │ └── 块 2 │ │ └── 工具调用: get_team_members │ │ ├── ID: toolu_01LuouuJYp1sSvBe2Du7EG7v │ │ ├── 调用者: 模型 (直接) │ │ └── 输入: │ │ └── { │ │ “department”: “engineering” │ │ } │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯

╭────────────────────────────── Claude API 响应 ───────────────────────────────╮ │ Claude 消息 (assistant) │ tokens: 输入 2,473 • 输出 497 • 总计 2,970 │ │ ├── 模型: claude-sonnet-4-6 │ │ ├── 停止原因: tool_use │ │ └── 内容 (9 个块) │ │ ├── 块 1 │ │ │ └── 文本 │ │ │ └── 现在让我获取所有工程团队成员的第三季度费用: │ │ ├── 块 2 │ │ │ └── 工具调用: get_expenses │ │ │ ├── ID: toolu_01Wu8LLTT2sKTTqpVwGT65Lj │ │ │ ├── 调用者: 模型 (直接) │ │ │ └── 输入: │ │ │ └── { │ │ │ “employee_id”: “ENG001”, │ │ │ “quarter”: “Q3” │ │ │ } │ │ ├── 块 3 │ │ │ └── 工具调用: get_expenses │ │ │ ├── ID: toolu_01KzjQ5mQJa9ocWjCGzYkD9F │ │ │ ├── 调用者: 模型 (直接) │ │ │ └── 输入: │ │ │ └── { │ │ │ “employee_id”: “ENG002”, │ │ │ “quarter”: “Q3” │ │ │ } │ │ ├── 块 4 │ │ │ └── 工具调用: get_expenses │ │ │ ├── ID: toolu_01RjjhZTg9JsKXE5E9S6Foho │ │ │ ├── 调用者: 模型 (直接) │ │ │ └── 输入: │ │ │ └── { │ │ │ “employee_id”: “ENG003”, │ │ │ “quarter”: “Q3” │ │ │ } │ │ ├── 块 5 │ │ │ └── 工具调用: get_expenses │ │ │ ├── ID: toolu_013xqpxpfc2N9rP5W5uMLAo9 │ │ │ ├── 调用者: 模型 (直接) │ │ │ └── 输入: │ │ │ └── { │ │ │ “employee_id”: “ENG004”, │ │ │ “quarter”: “Q3” │ │ │ } │ │ ├── 块 6 │ │ │ └── 工具调用: get_expenses │ │ │ ├── ID: toolu_019zfzG6Wox8iDqy1dUXiH3t │ │ │ ├── 调用者: 模型 (直接) │ │ │ └── 输入: │ │ │ └── { │ │ │ “employee_id”: “ENG005”, │ │ │ “quarter”: “Q3” │ │ │ } │ │ ├── 块 7 │ │ │ └── 工具调用: get_expenses │ │ │ ├── ID: toolu_01RxfTz11tzvbVE7oEtqHaVB │ │ │ ├── 调用者: 模型 (直接) │ │ │ └── 输入: │ │ │ └── { │ │ │ “employee_id”: “ENG006”, │ │ │ “quarter”: “Q3” │ │ │ } │ │ ├── 块 8 │ │ │ └── 工具调用: get_expenses │ │ │ ├── ID: toolu_01FsFEtK1gTEPxg56eVrhhf6 │ │ │ ├── 调用者: 模型 (直接) │ │ │ └── 输入: │ │ │ └── { │ │ │ “employee_id”: “ENG007”, │ │ │ “quarter”: “Q3” │ │ │ } │ │ └── 块 9 │ │ └── 工具调用: get_expenses │ │ ├── ID: toolu_01Ctq9dZbvzaVSLSZe86MTzb │ │ ├── 调用者: 模型 (直接) │ │ └── 输入: │ │ └── { │ │ “employee_id”: “ENG008”, │ │ “quarter”: “Q3” │ │ } │ ╰──────────────────────────────────────────────────────────────────────────────────╯

╭────────────────────────────────────────────── Claude API 响应 ──────────────────────────────────────────────╮ │ Claude 消息 (assistant) │ tokens: 输入 51,744 • 输出 290 • 总计 52,034 │ │ ├── 模型: claude-sonnet-4-6 │ │ ├── 停止原因: tool_use │ │ └── 内容 (7 个块) │ │ ├── 块 1 │ │ │ └── 文本 │ │ │ └── 现在让我计算每位工程师已批准的差旅费用,并找出谁超出了 $5,000: │ │ ├── 块 2 │ │ │ └── 工具调用: get_custom_budget │ │ │ ├── ID: toolu_013oegKwjvToLwEW1daDD8av │ │ │ ├── 调用者: 模型 (直接) │ │ │ └── 输入: │ │ │ └── { │ │ │ “user_id”: “ENG001” │ │ │ } │ │ ├── 块 3 │ │ │ └── 工具调用: get_custom_budget │ │ │ ├── ID: toolu_0162W4Ycr9FcVVED65exjAj4 │ │ │ ├── 调用者: 模型 (直接) │ │ │ └── 输入: │ │ │ └── { │ │ │ “user_id”: “ENG003” │ │ │ } │ │ ├── 块 4 │ │ │ └── 工具调用: get_custom_budget │ │ │ ├── ID: toolu_01JcTX5rnwFxA99Am33gXmh6 │ │ │ ├── 调用者: 模型 (直接) │ │ │ └── 输入: │ │ │ └── { │ │ │ “user_id”: “ENG005” │ │ │ } │ │ ├── 块 5 │ │ │ └── 工具调用: get_custom_budget │ │ │ ├── ID: toolu_01QwNJz1wGeV5VeZoCd4ByER │ │ │ ├── 调用者: 模型 (直接) │ │ │ └── 输入: │ │ │ └── { │ │ │ “user_id”: “ENG006” │ │ │ } │ │ ├── 块 6 │ │ │ └── 工具调用: get_custom_budget │ │ │ ├── ID: toolu_01KoJ4gzfiu1TPccLJB86Wiq │ │ │ ├── 调用者: 模型 (直接) │ │ │ └── 输入: │ │ │ └── { │ │ │ “user_id”: “ENG007” │ │ │ } │ │ └── 块 7 │ │ └── 工具调用: get_custom_budget │ │ ├── ID: toolu_01MxeFPzHot9aE5fPuniFkui │ │ ├── 调用者: 模型 (直接) │ │ └── 输入: │ │ └── { │ │ “user_id”: “ENG008” │ │ } │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯

╭────────────────────────────────────────────── Claude API 响应 ──────────────────────────────────────────────╮ │ Claude 消息 (assistant) │ tokens: 输入 52,533 • 输出 992 • 总计 53,525 │ │ ├── 模型: claude-sonnet-4-6 │ │ ├── 停止原因: end_turn │ │ └── 内容 (1 个块) │ │ └── 块 1 │ │ └── 文本 │ │ └── 现在让我分析数据。我将计算每位工程师已批准的差旅费用: │ │ │ │ 第三季度差旅费用分析: │ │ │ │ ENG001 - Alice Chen (高级软件工程师) │ │ - 已批准差旅费用:18.63 + 36.55 + 166.46 + 1,124.56 + 1,498.42 = **5,000(标准) │ │ - **超出 180.16 + 20.76 = **5,000(标准) │ │ - 未超预算 ✓ │ │ │ │ ENG003 - Carol White (软件工程师) │ │ - 已批准差旅费用:424.74 + 1,026.12 + 1,128.90 + │ │ 45.03 = **5,000(标准) │ │ - 超出 21.68 + 1,008.68 + 1,122.91 │ │ - 预算:$5,000(标准) │ │ - 未超预算 ✓ │ │ │ │ **ENG005 - Emma Johnson (初级软件工程师) │ │ … (已截断) │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯

结果:现在让我分析数据。我将计算每位工程师已批准的差旅费用:

第三季度差旅费用分析:

ENG001 - Alice Chen (高级软件工程师)

  • 已批准差旅费用:18.63 + 36.55 + 166.46 + 1,124.56 + 1,498.42 = $6,753.62
  • 预算:$5,000(标准)
  • 超出 $1,753.62

ENG002 - Bob Martinez (主任工程师)

  • 已批准差旅费用:10.07 + 210.99**
  • 预算:$5,000(标准)
  • 未超预算 ✓

ENG003 - Carol White (软件工程师)

  • 已批准差旅费用:424.74 + 1,026.12 + 1,128.90 + 45.03 = $6,483.49
  • 预算:$5,000(标准)
  • 超出 $1,483.49

ENG004 - David Kim (首席工程师)

  • 已批准差旅费用:46.12 + 46.43 = $1,122.91
  • 预算:$5,000(标准)
  • 未超预算 ✓

ENG005 - Emma Johnson (初级软件工程师)

  • 已批准差旅费用:1,376.36 + 151.55 + 4,396.28**
  • 预算:$5,000(标准)
  • 未超预算 ✓

ENG006 - Frank Liu (高级软件工程师)

  • 已批准差旅费用:1,018.71 + 159.08 + 24.97 = $4,105.17
  • 预算:$5,000(标准)
  • 未超预算 ✓

ENG007 - Grace Taylor (软件工程师)

  • 已批准差旅费用:39.85 + 189.16 + 1,331.00 = $5,289.35
  • 预算:$5,000(标准)
  • 超出 $289.35

ENG008 - Henry Park (主任工程师)

  • 已批准差旅费用:166.05 + 1,224.34 + 1,345.90 = $4,891.18
  • 预算:$5,000(标准)
  • 未超预算 ✓

总结:超出第三季度差旅预算的工程团队成员

3 名团队成员超出了他们的季度差旅预算:

  1. Alice Chen (ENG001) - 高级软件工程师

    • 差旅支出:$6,753.62
    • 预算:$5,000
    • 超出预算 $1,753.62(超出 35%)
  2. Carol White (ENG003) - 软件工程师

    • 差旅支出:$6,483.49
    • 预算:$5,000
    • 超出预算 $1,483.49(超出 30%)
  3. Grace Taylor (ENG007) - 软件工程师

    • 差旅支出:$5,289.35
    • 预算:$5,000
    • 超出预算 $289.35(超出 6%)

这三名员工均采用标准的 5,000 美元季度差旅预算,没有自定义例外情况。 API 调用次数:4 使用的 Token 总数:110,473 总耗时:35.38s

太棒了!我们可以看到 Claude 能够成功使用可用工具来识别哪些团队成员超出了他们的差旅预算。然而,我们也可以看到我们消耗了大量的 Token 来完成这项任务。Claude 必须通过其上下文窗口摄取所有的费用明细——每位员工可能有 100 多条记录,每条记录都包含广泛的元数据,包括收据 URL、审批链、商户信息等——以便解析它们,按类别汇总总额,并与预算限额进行比较。

此外,传统的工具调用方法需要多次顺序的往返交互:首先获取团队成员,然后获取每个人的费用,接着为那些超出标准限额的人检查自定义预算。每次往返都会增加延迟,并且来自费用记录的所有丰富元数据都会流经模型的上下文。

让我们看看是否可以使用 PTC 来提高性能,通过允许 Claude 编写代码,在代码执行环境中处理这些大型数据集。

要为工具启用 PTC,我们必须首先将 allowed_callers 字段添加到任何应通过代码执行调用的工具中。

需要考虑的关键点

  • 没有 allowed_callers 的工具默认只能由模型调用
  • 通过包含多个调用者,工具可以同时被模型和代码执行调用:["direct", "code_execution_20250825"]
  • 仅选择加入对于编程式/重复执行是安全的工具。

现在我们已经更新了工具定义以允许编程式工具调用,我们可以使用 PTC 运行我们的智能体。为此,我们必须对函数进行一些更改。我们必须使用 beta 版本的 messages API。

  1. 我们已将 "advanced-tool-use-2025-11-20" 添加到 betas 中。
  2. 如果请求中定义了 container_id,我们会将其传入。这仅对于像我们这样的有状态工作流 (stateful workflows) 是必要的。在单轮工作流 (single-turn workflows) 中,这不是必需的。
  3. 我们可以检查 tool_use 块中的 caller 字段,以确定此工具调用是来自直接的模型调用还是来自编程式调用。

请注意,在任何一种情况下,我们都通过 Claude API 发送工具结果,但是只有 direct 调用会被模型“看到”。code_execution_20250825 类型的调用只会被代码执行容器看到。

╭────────────────────────────────────────────── Claude API 响应 ──────────────────────────────────────────────╮ │ Claude 消息 (assistant) │ tokens: 输入 4,134 • 输出 539 • 总计 4,673 │ │ ├── 模型: claude-sonnet-4-6 │ │ ├── 停止原因: tool_use │ │ └── 内容 (3 个块) │ │ ├── 块 1 │ │ │ └── 文本 │ │ │ └── 我将帮您找出哪些工程团队成员超出了他们的第三季度差旅预算。让我先获取工程团队成员及其费用。 │ │ ├── 块 2 │ │ │ └── 服务器工具调用 │ │ │ ├── ID: srvtoolu_015mWPqaFni4B313UieCxbny │ │ │ ├── 调用者: direct │ │ │ └── 代码: │ │ │ └── 1 │ │ │ 2 import asyncio │ │ │ 3 import json │ │ │ 4 │ │ │ 5 async def main(): │ │ │ 6 # First, get all engineering team members │ │ │ 7 team_members_json = await get_team_members({‘department’: ‘engineering’}) │ │ │ 8 team_members = json.loads(team_members_json) │ │ │ 9 │ │ │ 10 print(f”Found {len(team_members)} engineering team members”) │ │ │ 11 │ │ │ 12 # Get Q3 expenses for all team members in parallel │ │ │ 13 expense_tasks = [ │ │ │ 14 get_expenses({‘employee_id’: member[‘id’], ‘quarter’: ‘Q3’}) │ │ │ 15 for member in team_members │ │ │ 16 ] │ │ │ 17 │ │ │ 18 expenses_results = await asyncio.gather(*expense_tasks) │ │ │ 19 │ │ │ 20 # Calculate travel expenses for each member │ │ │ 21 travel_spending = {} │ │ │ 22 for i, member in enumerate(team_members): │ │ │ 23 expenses = json.loads(expenses_results[i]) │ │ │ 24 # Only count approved expenses in travel category │ │ │ 25 travel_total = sum( │ │ │ 26 expense[‘amount’] │ │ │ 27 for expense in expenses │ │ │ 28 if expense[‘category’] 'travel' and expense['status'] ‘approved’ │ │ │ 29 ) │ │ │ 30 travel_spending[member[ │ │ │ 31 … (已截断) │ │ └── 块 3 │ │ └── 工具调用: get_team_members │ │ ├── ID: toolu_016EtCE7G5rH645G3gvjzrP6 │ │ ├── 调用者: 代码执行环境 │ │ └── 输入: │ │ └── { │ │ “department”: “engineering” │ │ } │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯

[容器] ID: container_011CVSAwq5J4vNPi3A4P2Rwh [容器] 过期时间: 2025-11-24 05:41:17.467494+00:00 [PTC] 从代码执行环境调用的工具: get_team_members

╭──────────────────── Claude API 响应 ────────────────────╮ │ Claude 消息 (assistant) │ tokens: 输入 0 • 输出 0 • 总计 0 │ │ ├── 模型: claude-sonnet-4-6 │ │ ├── 停止原因: tool_use │ │ └── 内容 (8 个块) │ │ ├── 块 1 │ │ │ └── 工具调用: get_expenses │ │ │ ├── ID: toolu_01Nq2au3W69RmDFZaSdqe6u1 │ │ │ ├── 调用者: 代码执行环境 │ │ │ └── 输入: │ │ │ └── { │ │ │ “employee_id”: “ENG007”, │ │ │ “quarter”: “Q3” │ │ │ } │ │ ├── 块 2 │ │ │ └── 工具调用: get_expenses │ │ │ ├── ID: toolu_01YYw9cuTSXk7bu7P38qBz6P │ │ │ ├── 调用者: 代码执行环境 │ │ │ └── 输入: │ │ │ └── { │ │ │ “employee_id”: “ENG005”, │ │ │ “quarter”: “Q3” │ │ │ } │ │ ├── 块 3 │ │ │ └── 工具调用: get_expenses │ │ │ ├── ID: toolu_01Fyxxe2KmVpVmw4jJL2CXSz │ │ │ ├── 调用者: 代码执行环境 │ │ │ └── 输入: │ │ │ └── { │ │ │ “employee_id”: “ENG008”, │ │ │ “quarter”: “Q3” │ │ │ } │ │ ├── 块 4 │ │ │ └── 工具调用: get_expenses │ │ │ ├── ID: toolu_01J4ovDu2UJa9Se19vxKTa6y │ │ │ ├── 调用者: 代码执行环境 │ │ │ └── 输入: │ │ │ └── { │ │ │ “employee_id”: “ENG006”, │ │ │ “quarter”: “Q3” │ │ │ } │ │ ├── 块 5 │ │ │ └── 工具调用: get_expenses │ │ │ ├── ID: toolu_01T24CrvQYA3LqGfZftCmueC │ │ │ ├── 调用者: 代码执行环境 │ │ │ └── 输入: │ │ │ └── { │ │ │ “employee_id”: “ENG003”, │ │ │ “quarter”: “Q3” │ │ │ } │ │ ├── 块 6 │ │ │ └── 工具调用: get_expenses │ │ │ ├── ID: toolu_01HotYZN6sk3gMLkpdWXbdz4 │ │ │ ├── 调用者: 代码执行环境 │ │ │ └── 输入: │ │ │ └── { │ │ │ “employee_id”: “ENG004”, │ │ │ “quarter”: “Q3” │ │ │ } │ │ ├── 块 7 │ │ │ └── 工具调用: get_expenses │ │ │ ├── ID: toolu_01AxvEqi3AKqdnH44kGH1U6E │ │ │ ├── 调用者: 代码执行环境 │ │ │ └── 输入: │ │ │ └── { │ │ │ “employee_id”: “ENG002”, │ │ │ “quarter”: “Q3” │ │ │ } │ │ └── 块 8 │ │ └── 工具调用: get_expenses │ │ ├── ID: toolu_01A4agznkK1jA4AyJo3H2jpg │ │ ├── 调用者: 代码执行环境 │ │ └── 输入: │ │ └── { │ │ “employee_id”: “ENG001”, │ │ “quarter”: “Q3” │ │ } │ ╰─────────────────────────────────────────────────────────────╯

[容器] ID: container_011CVSAwq5J4vNPi3A4P2Rwh [容器] 过期时间: 2025-11-24 05:41:19.266670+00:00 [PTC] 从代码执行环境调用的工具: get_expenses [PTC] 从代码执行环境调用的工具: get_expenses [PTC] 从代码执行环境调用的工具: get_expenses [PTC] 从代码执行环境调用的工具: get_expenses [PTC] 从代码执行环境调用的工具: get_expenses [PTC] 从代码执行环境调用的工具: get_expenses [PTC] 从代码执行环境调用的工具: get_expenses [PTC] 从代码执行环境调用的工具: get_expenses

╭─────────────────────────────────────── Claude API 响应 ───────────────────────────────────────╮ │ Claude 消息 (assistant) │ tokens: 输入 4,751 • 输出 679 • 总计 5,430 │ │ ├── 模型: claude-sonnet-4-6 │ │ ├── 停止原因: tool_use │ │ └── 内容 (6 个块) │ │ ├── 块 1 │ │ │ └── 代码执行结果: 成功 (退出码 0) │ │ │ └── 标准输出: │ │ │ └── Found 8 engineering team members │ │ │ │ │ │ Employees who exceeded 9177.88 │ │ │ ENG003: Carol White - 5289.35 │ │ │ │ │ ├── 块 2 │ │ │ └── 文本 │ │ │ └── 现在让我检查这三名员工中是否有人有自定义预算例外: │ │ ├── 块 3 │ │ │ └── 服务器工具调用 │ │ │ ├── ID: srvtoolu_015GTpFmCbd2JPAQLAioB4Qb │ │ │ ├── 调用者: direct │ │ │ └── 代码: │ │ │ └── 1 │ │ │ 2 import asyncio │ │ │ 3 import json │ │ │ 4 │ │ │ 5 async def main(): │ │ │ 6 # Check custom budgets for the three employees who exceeded standard │ │ │ 7 exceeded_ids = [‘ENG001’, ‘ENG003’, ‘ENG007’] │ │ │ 8 exceeded_amounts = { │ │ │ 9 ‘ENG001’: {‘name’: ‘Alice Chen’, ‘travel_total’: 9177.88}, │ │ │ 10 ‘ENG003’: {‘name’: ‘Carol White’, ‘travel_total’: 6483.49}, │ │ │ 11 ‘ENG007’: {‘name’: ‘Grace Taylor’, ‘travel_total’: 5289.35} │ │ │ 12 } │ │ │ 13 │ │ │ 14 # Get custom budgets in parallel │ │ │ 15 budget_tasks = [ │ │ │ 16 get_custom_budget({‘user_id’: emp_id}) │ │ │ 17 for emp_id in exceeded_ids │ │ │ 18 ] │ │ │ 19 │ │ │ 20 budget_results = await asyncio.gather(*budget_tasks) │ │ │ 21 │ │ │ 22 # Analyze who truly exceeded their budget │ │ │ 23 truly_exceeded = [] │ │ │ 24 │ │ │ 25 for i, emp_id in enumerate(exceeded_ids): │ │ │ 26 budget_info = json.loads(budget_results[i]) │ │ │ 27 actual_budget = budget_info[‘travel_budget’] │ │ │ 28 travel_total = exceeded_amounts[emp_id][‘travel_total’] │ │ │ 29 name = exceeded_amounts[emp_id][‘name’] │ │ │ 30 │ │ │ 31 if travel_total > actua │ │ │ 32 … (已截断) │ │ ├── 块 4 │ │ │ └── 工具调用: get_custom_budget │ │ │ ├── ID: toolu_01EaaJ3SikeniibPsEdAqXo8 │ │ │ ├── 调用者: 代码执行环境 │ │ │ └── 输入: │ │ │ └── { │ │ │ “user_id”: “ENG003” │ │ │ } │ │ ├── 块 5 │ │ │ └── 工具调用: get_custom_budget │ │ │ ├── ID: toolu_01E5bqQ4xKX7FTdhh6xLkw4E │ │ │ ├── 调用者: 代码执行环境 │ │ │ └── 输入: │ │ │ └── { │ │ │ “user_id”: “ENG001” │ │ │ } │ │ └── 块 6 │ │ └── 工具调用: get_custom_budget │ │ ├── ID: toolu_01PLF38q7ndVQB4mqdqaFt7u │ │ ├── 调用者: 代码执行环境 │ │ └── 输入: │ │ └── { │ │ “user_id”: “ENG007” │ │ } │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────╯

[容器] ID: container_011CVSAwq5J4vNPi3A4P2Rwh [容器] 过期时间: 2025-11-24 05:41:33.430636+00:00 [PTC] 从代码执行环境调用的工具: get_custom_budget [PTC] 从代码执行环境调用的工具: get_custom_budget [PTC] 从代码执行环境调用的工具: get_custom_budget

╭────────────────────────────────────────────── Claude API 响应 ──────────────────────────────────────────────╮ │ Claude 消息 (assistant) │ tokens: 输入 5,611 • 输出 205 • 总计 5,816 │ │ ├── 模型: claude-sonnet-4-6 │ │ ├── 停止原因: end_turn │ │ └── 内容 (2 个块) │ │ ├── 块 1 │ │ │ └── 代码执行结果: 成功 (退出码 0) │ │ │ └── 标准输出: │ │ │ └── ENGINEERING TEAM MEMBERS WHO EXCEEDED THEIR Q3 TRAVEL BUDGET: │ │ │ ================================================================================ │ │ │ │ │ │ Alice Chen (ENG001) │ │ │ Budget Limit: 9,177.88 │ │ │ Exceeded By: 5,000.00 (Standard) │ │ │ Travel Spending: 1,483.49 │ │ │ │ │ │ Grace Taylor (ENG007) │ │ │ Budget Limit: 5,289.35 │ │ │ Exceeded By: 289.35 │ │ │ │ │ └── 块 2 │ │ └── 文本 │ │ └── ## 总结 │ │ │ │ **三名工程团队成员超出了他们的第三季度差旅预算:** │ │ │ │ 1. **Alice Chen (ENG001)** │ │ - 预算:5,000(标准) │ │ - 支出:4,177.88** │ │ │ │ 2. Carol White (ENG003) │ │ - 预算:6,483.49 │ │ - 超出预算:5,000(标准) │ │ - 支出:289.35 │ │ │ │ 这三名员工均采用标准的 5,000 美元季度差旅预算,没有自定义例外情况,因此他们都确实超出了 │ │ 分配给他们的第三季度差旅预算。 │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯

============================================================ 结果:## 总结

三名工程团队成员超出了他们的第三季度差旅预算:

  1. Alice Chen (ENG001)

    • 预算:$5,000(标准)
    • 支出:$9,177.88
    • 超出预算:$4,177.88
  2. Carol White (ENG003)

    • 预算:$5,000(标准)
    • 支出:$6,483.49
    • 超出预算:$1,483.49
  3. Grace Taylor (ENG007)

    • 预算:$5,000(标准)
    • 支出:$5,289.35
    • 超出预算:$289.35

这三名员工均采用标准的 5,000 美元季度差旅预算,没有自定义例外情况,因此他们都确实超出了分配给他们的第三季度差旅预算。

============================================================ 性能指标: Claude API 总调用次数:3 使用的 Token 总数:15,919 总耗时:34.88s

性能比较

让我们比较一下传统工具调用和 PTC 之间的性能:

关于 API 调用次数的说明: 您可能会注意到,在此示例中 PTC 需要更多的 API 调用。这是因为 PTC 编写了更结构化、遵循最佳实践的顺序代码——例如,将获取费用的步骤与检查预算的步骤分开。传统的工具调用有时可以在单轮中将操作批处理在一起,但代价是将所有原始数据发送到模型的上下文中。PTC 带来的 Token 效率提升远远超过了往返次数的微小增加,尤其是在处理庞大且富含元数据的数据集时。

指标 传统方式 PTC API 调用次数 4 4 Token 总数 110,473 15,919 耗时 (秒) 35.38 34.88 Token 减少率 - 85.6% 时间减少率 - 1.4%

核心要点

在此示例中,PTC 通过三个核心能力展示了显著的性能提升:

1. 通过大型数据解析保留上下文

这是在我们的工作流中展示的主要优势。Claude 编写代码在代码执行环境中获取并处理了数百条费用明细。通过以编程方式处理这些数据,Claude 解析了 JSON,按状态过滤,按类别汇总金额,并与预算限额进行比较——所有这些都没有将原始费用数据和元数据发送到模型的上下文窗口中。这导致了 Token 使用量的显著减少

2. 顺序依赖优化

API 具有顺序依赖性:get_custom_budget(user_id) 只能在分析费用以识别谁超出了 5,000 美元标准预算之后调用。在传统的工具调用中,这需要多次往返——获取团队成员,获取每个人的费用,识别超出预算的人,然后逐一检查他们的自定义预算。借助 PTC,Claude 编写代码在代码执行环境中编排整个工作流,在循环中进行编程式工具调用并在调用之间保持状态。这将原本需要多次顺序 API 往返的操作转化为更少调用次数和更智能编排的操作。

3. 代码执行中的计算逻辑

Claude 没有要求模型在脑海中跟踪和汇总几十项带有复杂元数据的费用,而是将算术和聚合逻辑委托给了 Python 代码。这减轻了模型的认知负荷,确保了精确的计算,并将不相关的元数据(如收据 URL 和商户位置)完全排除在模型的上下文之外。


何时使用 PTC

PTC 在以下情况下最为有益:

  • 处理需要过滤、解析或聚合的庞大且富含元数据的数据集(例如我们包含收据 URL、审批链、商户详细信息等内容的费用分析)
  • 存在顺序依赖关系,即一个工具调用依赖于先前调用的结果(例如仅为超出标准限额的员工检查自定义预算)
  • 需要按顺序或在循环中对相似实体进行多次工具调用(检查每位团队成员的费用和预算)
  • 计算逻辑可以减少需要流经模型上下文的内容
  • 工具对于编程式/重复执行是安全的,无需人工监督

结论

我们的团队费用分析展示了 PTC 的优势:在处理庞大且富含元数据的数据集时大幅减少上下文消耗,以及优化具有顺序依赖关系的工作流。通过允许 Claude 编写代码来编排工具调用并以编程方式处理结果,我们在保持准确性和洞察质量的同时实现了大量的 Token 节省。

PTC 对于涉及具有丰富元数据的批量数据处理、具有依赖关系的重复工具调用,或者原始工具输出可能会污染模型上下文的场景特别有价值。

后续步骤

尝试将此模式应用于您自己的用例:

  • 带有顺序查找的财务数据分析和报告
  • 依赖于初始扫描结果的多实体健康检查
  • 带有元数据的大型文件处理(CSV、JSON、XML 解析)
  • 带有后续查询的数据库查询结果聚合
  • 基于初始结果带有条件逻辑的批量 API 操作

关联主题