让模型写一段代码,由代码在沙箱里直接调用工具并处理结果,而不是每次工具调用都让模型往返一轮。核心收益是把工具调用的 O(N) 模型轮次压到 O(1),并让中间态数据在进入模型上下文之前就被代码过滤掉。

传统工具调用 vs PTC

传统 tool calling(JSON function calling)的循环是:模型输出 tool_use → 宿主执行 → 结果回灌上下文 → 模型再决策。工具数量多、返回结果大时,延迟和 token 都被放大,且大量无关中间数据会稀释注意力。

PTC 把这一步换成:模型生成一段程序(循环、条件分支、并行、过滤、聚合),程序在 Code Execution 环境中调用被授权的工具,只把最终需要的信息带回模型上下文。

维度传统 Tool CallingPTC
交互轮次每次调用一轮,O(N)一段代码内完成,O(1)
中间结果全部回灌上下文留在沙箱,按需过滤后再回传
控制流由模型逐轮隐式表达代码里显式写循环/分支/并行
典型痛点结果长、工具多时 token 爆炸对模型代码规划能力要求高
执行位置宿主进程隔离的 Code Execution 容器

工作原理(Claude API 为例)

  1. 在工具定义上加 allowed_callers:
    • ["code_execution_20250825"]:只允许代码调用
    • ["direct", "code_execution_20250825"]:模型直呼和代码调用都允许
    • 不加则默认只允许模型直呼;只应对可安全重复执行的工具开放
  2. 追加服务端 code_execution_20250825 工具,提供代码执行环境
  3. 请求走 beta messages API,带 advanced-tool-use-2025-11-20 beta
  4. 多轮有状态场景透传 container_id 复用执行容器
  5. 通过 tool_use block 的 caller 字段区分来源:
    • direct:模型直呼,结果会被模型看到
    • code_execution_20250825:代码调用,结果只进入执行容器,不进入模型上下文

关键点:无论哪种调用,宿主仍负责实际执行工具并把 tool_result 发回 API,PTC 改变的是结果去哪、由谁编排,不是工具本身的实现。

收益与适用场景

  • 数据密集的批量读取:一次拉取上百条记录,在代码里做过滤/求和/join,只回传结论(官方 expense 示例)
  • 有顺序依赖的多步 API:先查列表 → 逐项查详情 → 条件触发补充查询
  • 并行扇出:用 asyncio.gather 之类并发调用多个工具
  • 第三方 API 不可改造:无法给 API 加预处理层时,用 PTC 在调用侧裁剪上下文

边界与风险

  • 对模型代码能力要求高:比 JSON tool call 更容易写错,调试链路更长
  • 安全面扩大:工具可被代码反复调用,必须限制 allowed_callers 并依赖沙箱权限
  • 不改变工具执行位置:真实副作用仍发生在宿主/后端,沙箱只负责编排与数据加工
  • 有状态容器生命周期:长流程需管理 container 过期与重启
  • 并非所有模型/平台都原生支持:各 harness 的实现方式差异较大(Code Mode SDK、持久 kernel、REPL 等)

与其他概念的关系

  • principles — Dynamic Workflow 的 agent()/pipeline() 本质是”代码编排 Agent”,PTC 是”代码编排工具”,同属 code-as-orchestrator
  • building-effective-agents — PTC 让 Orchestrator-Workers / Parallelization 模式更省上下文
  • agent-harness-anatomy — PTC 属于 Harness 的 Bash + Code 执行与工具调用 offloading 层
  • oh-my-pi — 持久 Python/Bun kernel 内回调 Agent 工具,是 PTC 思路的一种工程实现
  • prime-agent — RLM 范式把工具调用做成持久 REPL 内的函数调用
  • agent-protocols — PTC 与 MCP/A2A 的层次区别:MCP 定义怎么连工具,PTC 定义谁来编排调用

参考