如果你正在维护一个需要连续查数据、筛选、去重、聚合再输出报告的 AI Agent,常见痛点并不是模型“不会调用工具”,而是中间结果太多、往返轮次太长、成本和延迟难以预测。本文面向已经用过 Function Calling 或 Responses API 的开发者,解释 GPT-5.6 的 Programmatic Tool Calling(程序化工具调用,简称 PTC)适合什么任务,并给出一套可落地的编排与评估方法。
从“模型逐步思考”到“程序批量处理”
传统工具调用通常是一个交替循环:模型决定调用哪个工具,应用执行工具,结果再交给模型判断下一步。这个模式的优势是每一步都能重新做语义判断,遇到异常也容易改变计划;缺点是当任务包含几十个结构相同的调用时,大量中间数据会反复进入模型上下文。
PTC 的思路不同。模型先写出一段受控程序,让程序在托管运行环境中调用被明确授权的工具,并在本地完成过滤、连接、排序、聚合或校验,只把压缩后的结构化结果交回模型。它不是“让模型拥有任意代码执行权”,而是把一段边界清楚、可验证的数据处理阶段交给程序完成。
#mermaid-svg-uIqBp2yuEAHGLa0Q{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-uIqBp2yuEAHGLa0Q .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-uIqBp2yuEAHGLa0Q .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-uIqBp2yuEAHGLa0Q .error-icon{fill:#552222;}#mermaid-svg-uIqBp2yuEAHGLa0Q .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-uIqBp2yuEAHGLa0Q .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-uIqBp2yuEAHGLa0Q .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-uIqBp2yuEAHGLa0Q .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-uIqBp2yuEAHGLa0Q .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-uIqBp2yuEAHGLa0Q .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-uIqBp2yuEAHGLa0Q .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-uIqBp2yuEAHGLa0Q .marker{fill:#333333;stroke:#333333;}#mermaid-svg-uIqBp2yuEAHGLa0Q .marker.cross{stroke:#333333;}#mermaid-svg-uIqBp2yuEAHGLa0Q svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-uIqBp2yuEAHGLa0Q p{margin:0;}#mermaid-svg-uIqBp2yuEAHGLa0Q .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-uIqBp2yuEAHGLa0Q .cluster-label text{fill:#333;}#mermaid-svg-uIqBp2yuEAHGLa0Q .cluster-label span{color:#333;}#mermaid-svg-uIqBp2yuEAHGLa0Q .cluster-label span p{background-color:transparent;}#mermaid-svg-uIqBp2yuEAHGLa0Q .label text,#mermaid-svg-uIqBp2yuEAHGLa0Q span{fill:#333;color:#333;}#mermaid-svg-uIqBp2yuEAHGLa0Q .node rect,#mermaid-svg-uIqBp2yuEAHGLa0Q .node circle,#mermaid-svg-uIqBp2yuEAHGLa0Q .node ellipse,#mermaid-svg-uIqBp2yuEAHGLa0Q .node polygon,#mermaid-svg-uIqBp2yuEAHGLa0Q .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-uIqBp2yuEAHGLa0Q .rough-node .label text,#mermaid-svg-uIqBp2yuEAHGLa0Q .node .label text,#mermaid-svg-uIqBp2yuEAHGLa0Q .image-shape .label,#mermaid-svg-uIqBp2yuEAHGLa0Q .icon-shape .label{text-anchor:middle;}#mermaid-svg-uIqBp2yuEAHGLa0Q .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-uIqBp2yuEAHGLa0Q .rough-node .label,#mermaid-svg-uIqBp2yuEAHGLa0Q .node .label,#mermaid-svg-uIqBp2yuEAHGLa0Q .image-shape .label,#mermaid-svg-uIqBp2yuEAHGLa0Q .icon-shape .label{text-align:center;}#mermaid-svg-uIqBp2yuEAHGLa0Q .node.clickable{cursor:pointer;}#mermaid-svg-uIqBp2yuEAHGLa0Q .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-uIqBp2yuEAHGLa0Q .arrowheadPath{fill:#333333;}#mermaid-svg-uIqBp2yuEAHGLa0Q .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-uIqBp2yuEAHGLa0Q .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-uIqBp2yuEAHGLa0Q .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-uIqBp2yuEAHGLa0Q .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-uIqBp2yuEAHGLa0Q .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-uIqBp2yuEAHGLa0Q .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-uIqBp2yuEAHGLa0Q .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-uIqBp2yuEAHGLa0Q .cluster text{fill:#333;}#mermaid-svg-uIqBp2yuEAHGLa0Q .cluster span{color:#333;}#mermaid-svg-uIqBp2yuEAHGLa0Q div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-uIqBp2yuEAHGLa0Q .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-uIqBp2yuEAHGLa0Q rect.text{fill:none;stroke-width:0;}#mermaid-svg-uIqBp2yuEAHGLa0Q .icon-shape,#mermaid-svg-uIqBp2yuEAHGLa0Q .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-uIqBp2yuEAHGLa0Q .icon-shape p,#mermaid-svg-uIqBp2yuEAHGLa0Q .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-uIqBp2yuEAHGLa0Q .icon-shape .label rect,#mermaid-svg-uIqBp2yuEAHGLa0Q .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-uIqBp2yuEAHGLa0Q .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-uIqBp2yuEAHGLa0Q .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-uIqBp2yuEAHGLa0Q :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
否
是
用户目标
模型规划
是否为有界批处理?
直接工具调用
PTC 程序
允许调用的工具
过滤/去重/聚合
小型结构化结果
模型完成语义判断
关键变化可以概括为:直接调用把“每个结果都交给模型看”,PTC 则把“规则明确的中间加工”下沉到程序。前者适合探索,后者适合稳定的数据流水线。
哪些任务适合 PTC
判断标准不是“工具多不多”,而是中间阶段能否被明确描述为一个有限计算问题。以下任务通常适合:
| 批量读取同构记录 | 调用之间相互独立,可并发 | 通过校验的记录数组 |
| 多来源数据连接 | 连接键和冲突规则明确 | 按 ID 合并后的对象 |
| 排名与去重 | 比较函数可以写清楚 | Top 20 与淘汰原因 |
| 指标聚合 | 计算过程确定,不需语言判断 | 分组统计与异常列表 |
| 格式验证 | 输入输出模式稳定 | 错误码、字段、证据 |
相反,以下情况应保留直接工具调用:只需要一次调用;工具结果很小;每一步结果都可能改变下一步策略;调用涉及用户审批;最终回答必须完整保留原生引用或文件。尤其是审批场景,不应把决定和执行都包进不可见的批处理程序。
一个实用问题是:“如果把中间结果换成表格,普通程序员能否仅靠规则完成处理?”答案为“能”时,PTC 往往值得评估;答案为“还要理解语境、判断例外”时,应让模型在关键节点重新参与。
一个有边界的日志分析示例
假设我们有两个只读工具:list_services() 返回服务清单,query_errors(service, window) 返回错误摘要。目标是找出最近一小时错误率最高的 10 个服务,并保留可审计证据。
不要只写“高效使用 PTC”。应该把程序阶段的合同写清楚:
使用程序化工具调用完成有界的数据阶段:
1. 仅允许调用 list_services 与 query_errors。
2. 服务查询最多并发 8 个,单服务失败最多重试 1 次。
3. 过滤请求量少于 100 的服务,按 error_rate 降序排列。
4. 输出最多 10 项,每项包含 service、request_count、error_count、error_rate、evidence_id。
5. 不执行任何写操作;若成功服务少于总数的 90%,返回 structured_failure。
最终根因判断和处置建议仍由模型通过直接推理完成。
这段合同包含六类真正影响可靠性的约束:允许的工具、并发量、重试次数、过滤规则、输出模式和停止条件。程序执行只是中间层,最终答案仍需检查数据是否完整、证据是否能追溯,以及是否遗漏用户要求。
接入时必须处理的输出类型
根据 OpenAI 当前模型指导,启用 PTC 时需要加入 programmatic_tool_calling 工具,并在可被程序调用的工具上设置允许的调用者。应用侧不能只等待普通函数调用,还要正确处理 program、由程序发起的函数调用以及 program_output 等输出项,并保留 call_id 和 caller 的关联。
这意味着接入代码至少要有三层状态:
如果应用丢失调用关联,常见后果不是立刻报错,而是把某次工具结果接到错误的请求上,导致“看起来合理、实际上串线”的答案。因此,调用标识应当作为数据模型的一部分持久化,而不是仅打印到日志。
如何评估是否真的更好
工具调用次数减少并不等于产品质量提高。建议在一组固定样本上同时运行直接调用版和 PTC 版,至少记录以下指标:
- 任务完成率:最终结果是否满足全部验收条件;
- 证据完整率:每个关键结论是否能回溯到工具结果;
- 最终答案完整度:程序输出正确时,模型是否仍遗漏字段;
- 总 Token、端到端延迟和费用;
- 工具调用数、失败数、重试数与并发峰值;
- 人工复核发现的错误类型。
评估时要特别检查 program_output 与最终消息之间的差异。程序可能返回了完整的 10 条记录,但最终消息只讲了 8 条;也可能程序正确标记部分失败,而总结时把结果说成“全部成功”。对生产系统而言,这类最后一公里损失和工具执行错误同样重要。
可以把上线门槛设为:任务完成率不下降、证据完整率不下降,在此基础上再比较成本和延迟。先守住质量,再谈效率。
安全与可运维设计
PTC 最适合只读或风险较低的计算阶段。对于删除、发布、转账、修改权限等操作,应当保留显式审批和直接执行边界。即使程序只能调用白名单工具,也要限制单次调用数量、参数范围、网络目标、执行时间和结果大小。
运维侧建议把以下字段写入结构化日志:程序版本哈希、允许工具列表、每次调用的 caller、输入摘要、输出摘要、错误类型、重试原因和停止条件。不要记录访问令牌、完整用户数据或不必要的工具原文。
最后准备三个降级路径:PTC 不可用时退回直接调用;部分工具失败时返回部分结果和缺口;程序输出未通过模式校验时不继续做自动动作。可降级的 Agent 往往比“所有逻辑一次跑完”的 Agent 更容易长期维护。
实施清单
把一个现有流程迁移到 PTC,可以按以下顺序进行:
PTC 的价值不在于“让 Agent 更自治”,而在于把确定性的中间处理变成边界可见、成本可测的程序阶段。只要坚持有界任务、最小授权、结构化证据和最终复核,它就能有效缩短长链路 Agent 的往返,同时不牺牲可审计性。
参考资料
- OpenAI Model guidance:GPT-5.6 与 Programmatic Tool Calling(OpenAI Developers,访问于 2026-09-03)
- GPT-5.6 Sol 模型说明(OpenAI Developers,访问于 2026-09-03)
网硕互联帮助中心





评论前必须登录!
注册