工具调用中断怎么办?APX的显式结束标记

中断的工具调用必须在对话历史中显式收尾,避免模型编造结果。
文章指出 AI Agent 的工具调用常因崩溃、超时或用户停止而中断,留下只有请求没有结果的悬空调用。这种半截状态会让下一回合继承模糊语义,诱导模型编造从未发生的结果,甚至基于未完成的动作继续推理、误判副作用。APX 在修复聊天历史时遵循严格序列规则,为每个未回答的调用补上“not run: the turn was interrupted”记录,它只声明没有收到工具结果,而不宣称外部动作失败,从而为安全重试保留判断空间。文章进一步区分可移植项目上下文(APC)与本地执行状态(APX):前者提供持久意图,后者保留诚实的操作事实。恢复时应分开回答是否请求工具、是否收到结果、什么检查安全三个问题。
为什么中断的工具调用需要显式收尾
AI Agent 在调用工具时可能还没拿到结果就“丢掉了回合”——浏览器崩溃、服务商超时、运行时重启,或者用户主动停止。这种中断是常态,但假装它没发生过则不是。APX 在修复聊天历史时遵循一条简单规则:中断的工具调用必须在对话历史中拥有一个显式结局。它不会留下悬空的请求,而是记录下“该工具因回合中断而未运行”。

这条规则看似微小,却直击工具调用 API 的结构性要求:严格序列。助手消息请求工具,紧跟着必须有一个对应的工具结果。如果历史中只有请求没有结果,下一回合就会继承一个模糊状态——浏览器搜索到底发生了吗?文件写入了吗?重试是否安全?模型不该靠猜,后来的读者也不该从一条“请求动作”的助手消息中推断出“动作成功”。
工具调用 API 的“严格序列”要求源自现代大模型函数调用(Function Calling)协议的设计约束:对话消息被划分为 assistant(可携带 tool_calls)、tool(携带 tool_call_id 与结果)等角色,服务端在解析历史时通常要求每个 tool_call 都必须有一个 id 匹配的 tool 消息紧随其后,否则会直接返回 400 错误或行为未定义。这条约束并非某家厂商的私有实现,而是 OpenAI Chat Completions、Anthropic Messages 等主流接口的共同规范,目的是让模型能够把“请求动作”和“动作结果”当作一个不可分割的原子单元来理解。当历史中只剩半截调用时,模型看到的不是“未知”,而是一个语法上不完整、语义上却像已发生的动作,这正是编造风险的来源。
悬空调用带来的真实风险
设想一段很短的对话历史:
用户:检查部署仪表板。
助手:调用 browser_text({ url: ... })
[进程中断]
用户:它发现了什么?
如果不做修复,最后一个问题就是在邀请模型编造。一个听起来合理的回答可能像模像样地总结仪表板,但实际上根本不存在任何结果。这比一个可见的中断更糟,因为它把缺失的证据变成了断言。
工具调用的“半截”状态还会污染后续推理。模型可能基于一个从未完成的动作继续规划,或者错误地认为某个副作用已经发生。在需要幂等性或副作用的场景中,这种混淆可能导致重复写入或遗漏检查。
“幂等性”指同一操作执行一次与执行多次对系统状态产生的效果相同。读取仪表板、查询任务状态这类只读操作天然幂等,重复执行无副作用;而写入文件、发送消息、创建订单、扣减库存等操作则非幂等,重复执行可能造成重复写入或重复扣款。这正是中断调用最棘手的地方:仅凭历史无法判断副作用是否已经发生。一个稳妥的恢复策略是优先采用幂等检查(例如先查询资源当前状态再决定是否写入),或者引入幂等键(idempotency key)让外部服务自行去重,而不是盲目重试。文章强调“not run”记录只说明没有收到结果、不宣称外部失败,原因也在于此——它把判断副作用是否发生的责任交还给调用方,而非替调用方下结论。
APX 如何修复结构而非故事
APX 的运行时历史修复逻辑从真实的用户条目开始,忽略孤立的工具结果,并检查每个助手工具调用是否有匹配的结果。当新的非工具条目出现,或者历史结束时,任何未回答的调用都会用一条显式记录关闭:
not run: the turn was interrupted
修复后的历史变成:
用户:检查部署仪表板。
助手:调用 browser_text({ url: ... })
工具:not run: the turn was interrupted
用户:它发现了什么?
这条记录刻意保持狭窄。它不声称动作在外部世界失败了——请求可能在运行时失联前已经到达外部服务。它只说明 APX 没有该回合已完成的工具结果。这个区分对重试至关重要:安全的下一步可能是检查当前状态、询问用户,或者运行一个幂等检查,而不是自动“再做一次”。
可移植上下文与运行时状态的边界
这项修复属于运行时工作,而不是对项目上下文的修改。APC 保持可移植契约:仓库中的 AGENTS.md、.apc/ 元数据、Agent 定义、技能以及安全的共享指引。兼容工具可以从另一个检出中读取该契约。
APX 是日常使用的运行时。它的聊天历史、工具调用记录、会话和中断标记都是本地执行状态。它们必须描述特定对话中发生了什么,但不属于可移植的项目契约。
这条边界让恢复更容易推理。APC 仍然告诉 Agent 重启后适用哪些项目规则和技能;APX 则单独告诉它上一次工具调用是否产生了证据。一层提供持久意图,另一层保留诚实的操作事实。
可移植上下文与本地运行时状态的分离,本质上是“声明式配置”与“命令式执行记录”的分离。前者描述系统应当处于什么规则之下(项目约定、Agent 定义、可用技能),可以随仓库版本化、跨机器复用;后者描述某次执行实际发生了什么(消息序列、工具调用、中断标记),具有会话局部性和时效性。如果把执行状态混入可移植契约,会导致契约随每次运行而漂移,其他检出无法复现;反之,如果把项目规则塞进运行时状态,重启后就丢失了意图。两层各自承担不同职责,恢复时才能分别回答“现在适用哪些规则”和“上一次动作到底做成了没有”这两个正交的问题。
实用的恢复习惯
当一次依赖工具的回合被中断时,把三个问题分开:
- 是否请求了工具?
- APX 是否收到了匹配的结果?
- 继续之前什么检查是安全的?
只有第二个问题能从修复后的历史中得到确定答案。第三个问题取决于操作本身:检查只读仪表板、查看任务状态,或者在重复写入前先询问。
显式的中断标记并不起眼,但它阻止了一类微妙的 Agent 错误。APC 让项目上下文保持可移植,APX 让执行历史保持可问责。下一回合便可以基于证据继续,而不是从一个看起来像成功的缺口继续。
相关推荐

花旗14000名工程师用Devin,技术外包账单砍掉30%
花旗集团14000名工程师使用AI编程智能体Devin,一年内将技术供应商账单削减30%,产品发布提速30-40%。但30%仅限单一成本项,摩根大通同期表示AI收益尚未体现在财报中,揭示企业AI落地的真实分化。

AI写代码,程序员要失业?Devin自主编程真相
Devin等自主AI编程代理正改变软件开发:从Copilot辅助编码到全自动工程代理,程序员角色从写代码转向系统设计与监督。本文分析AI编程对就业、代码安全、初级开发者培养的影响,以及效率悖论下程序员需求的真实走向。

AGENTS.md 实战指南:让编程 Agent 真正好用
AGENTS.md 和 CLAUDE.md 能显著提升编程 Agent 表现,但研究发现用错反而让成本上升 20%。本文详解该写什么、该删什么、200 行与 32KB 的硬边界、Monorepo 嵌套规则及安全提醒。