追加输入进队列、带预期轮次编号防串线、取消收尾与工具竞态,以及中断后如何用文件/进程/远端三类证据核对。
Agent 正在工作时你突然说「方向变了」或「先停」——系统该把这句话放在哪里?怎么停已经开始的动作?第十一章讲运行中干预。例子:原要求是修测试并保持旧接口;做到一半你说「先别改实现,只把原因和测试方案整理出来」——既改交付内容,也可能影响正在跑的工具。
先分开两条时间线
一次模型请求:把当时准备好的上下文发给模型,接收回答与工具调用。一个轮次可能更长,包含多次请求与多次工具执行。用户补充可能出现在其中任一位置,不只在两轮对话之间。请求已发出时,新文字需要找到下一次处理机会——收到消息的时刻与模型真正用它做下一步决定的时刻之间,可能还有采样与工具在进行。讨论「能不能及时转向」时,要说清正在等待什么、哪一轮在执行、输入何时进入后续请求。追加要求与立即停止,工程含义不同。
入口:启动或引导当前轮次
核心提供可启动也可引导当前轮次的入口:检查实际运行状态;有活动轮次则尝试把新要求送进去;没有才走启动新任务路径。并非无条件接收——服务正在结束、任务类型不支持引导等,提交可能被拒绝。返回会区分:已启动、已送入现有轮次、未提交成功。客户端应按核心返回的事实更新界面,不能把文字出现在输入框旁就当成模型已读到。
「先做分析」被送入现有轮次后,还要经过队列与请求准备:入口负责接收与归属,后面一层才把新约束变成模型接下来能看到的信息。
进入队列之后何时被消费
新要求进入运行中的普通轮次后,先放进该轮次的待处理输入;队列会发活动通知,但不等于立刻把当前模型采样换成一份新请求。主循环在允许读取新输入的位置取出内容,经输入处理、记入历史,随后在准备请求时模型才有机会同时看到原任务、已取得结果与用户补充。采样及本次工具处理之后,循环还会检查有无待处理输入——即使模型这次没要求继续,队列里还有输入也可能需要继续处理。代码没有把「这一次回答结束」等同于「整个轮次必然结束」。正确解释是:补充被安排进入后续处理,不能保证之前已发出的修改调用从未执行。若希望立即打断原方向,要单独看中断路径。
预期轮次编号:避免送到错误任务
界面显示轮次 A 在跑,消息到达时 A 可能已结束、甚至轮次 B 已开始。若仍按旧界面判断,要求可能送到错误地方。引导入口可带上预期轮次编号;核心拿到活动轮次后比较实际编号与预期,不一致就返回不匹配——不会偷偷把输入改到另一个轮次。同时检查任务是否可引导、输入格式是否符合。关键不是让用户记住编号,而是调用方明确想干预谁,并处理状态已变化的结果。产品侧:界面状态可能过时,操作请求最好带着要操作的对象;被拒绝后重新读状态再决定,而不是自动把同一句话重复发到新任务。
明确「先停」:取消路径
处理的是活动任务的取消,不只是往消息队列再塞一句自然语言。先取消任务持有的信号,让正在运行的组件能观察到;随后等待任务自行结束(有上限);无论正常观察到取消还是等到期限,外层都继续做任务句柄与专属清理,再记录终止状态。中断不是瞬间完成的布尔开关——从发信号到资源收尾有实际工作。某些组件还有自己的中断处理(例如满足条件时通知 Code Mode 活动单元)。对使用者:「停止请求已发出」与「当前轮次已终止」应分开显示;对实现者:取消信号要一路传下去,并留出明确收尾路径。
工具刚好在取消时完成
读测试文件已完成、结果正在返回,用户同时点停止——不能只因取消信号到了就把这次真实完成的调用抹掉。工具调度会同时观察调用结果与取消信号:已到达终态或执行任务已结束就收取结果;仍在运行则尝试终止调度任务,再按最终返回结果还是被取消做收尾。工具有没有完成要依据实际生命周期判断;取消处理也不能把过去的成功结果统一改成失败,否则恢复与分析会失去可靠依据。外部命令、远程服务或插件内部怎么停,还要看具体工具实现——调度任务结束不足以证明所有外部动作都被撤销。
卡在审批等待时停止
若只是先关审批通道,等待方可能把它解释成一次普通拒绝,还没来得及知道轮次已被中断。Codex 在清理顺序上特意处理:先执行任务取消与中断收尾,再清理当前轮次的等待事项与缓冲输入,减少审批等待被错误呈现为另一种业务结果的机会。中断后真正重要的是确认当前状态;若要改范围,最好在新交接里把保留条件再说清楚,不要依赖尚未消费的旧输入。
中断后核对三类证据
「先别改实现」时,文件可能已写一半,也可能写完只是还没汇报。轮次显示中断,不能告诉我们磁盘究竟处在哪一种状态。重新开始前要:读当前文件与差异;查询测试命令进程是否还存活;若涉及远端服务,核对服务端有没有接受操作。
- 对话记录:当时发出了什么请求;
- 工具结果:返回了什么信息;
- 外部系统当前状态:实际发生了什么。
三者可能因中断时机暂时对不上。恢复动作应先确认再决定保留、不做或必要撤销,而不是把再次提交任务当成安全万能重试——尤其对重复执行会产生副作用的操作。
改需求时交接写清楚
最怕只留下一句抽象的「换个办法」。更明白的交接例如:停止继续修改实现;保留刚才读到的测试证据;给出空字符串问题的原因与测试方案;仍保留旧接口约束。停止项、保留项、新任务要和真实文件关联起来。这不是 Codex 自动生成的改需求模板,而是从输入队列与取消机制里得到的使用方法:按原轮次追加输入,会让后续请求获得这些条件;若已中断,就根据实际状态发起新的明确交接。两种路径都需要让模型看到完整目标。
机制串联
新要求经入口确认归属 → 进入可接收轮次或启动新轮次 → 队列在合适位置被消费并组织进后续模型请求。需要立刻结束原方向时走取消与清理:处理运行中任务、工具竞态与等待项,再发出终止事件——与模型主动给出最终回答是不同的结束原因。结束后仍要核对文件、进程与外部服务,再带着明确新要求继续。既不把「已接收」当成「已采用」,也不把「已中断」当成「所有动作都没发生」。
下一期(合集文字稿未单独收录持久化恢复专题)之后,系列收官篇讲测试与可观测性:如何用证据验证 Agent 行为。