用户让Agent整理一份资料目录。工具很快返回“已受理”,还带了一个任务编号。Agent把这句话改写成:“目录已经整理好了。”
几分钟后,后台任务因为源文件不可读而失败。用户手里没有目录,只有一段过早的完成通知。
这不是模型漏读了某个复杂异常,而是运行层少区分了一张收据:受理回执证明请求进入了处理流程,完成回执才可能证明结果已经产生;结果是否满足要求,还得再验。 本文只讨论长任务工具:怎样从一次短请求,接住一个尚未结束的业务过程。
AI原创概念插画:红绒盒里的鹭鸟徽牌、空玻璃罩、炉前玻璃鸟与壁龛中的玻璃鹭鸟并置,借凭牌与成品的区别作比喻。画面不证明具体制作阶段,也不是真实玻璃工艺或系统状态的复原。
一、202不是迟一点兑现的200
HTTP的 202 Accepted 表示请求已被接受处理,但处理尚未完成。RFC 9110第15.3.3节还特意指出:请求最终可能执行,也可能不执行;HTTP没有让服务端事后重新发送一次状态码、替换原来那次响应的机制。[1]
所以,不能把202翻译成“成功,只是页面还没刷新”。后续结果需要另一条可查询的通道。
Azure的异步请求—应答模式给出一种实现:初始请求迅速返回202与状态查询位置,后台继续工作;客户端之后查询状态。状态查询本身返回200,也可能只是成功读到了“仍在运行”。 文档明确提醒,不同服务的具体语义并不一致。[2]
Google AIP-151则针对采用其规范的API,建议长操作返回 google.longrunning.Operation,通过操作资源追踪进度和取得结果。[3] 这不是说所有工具都必须用Google的字段,更不是说所有异步函数都应返回202。这里借两种官方设计说明同一件事:启动动作与追踪动作应当能区分。
| 看到的证据 | 此时可以说什么 | 此时不能说什么 |
|---|---|---|
| 已受理,拿到操作句柄 | 请求已进入处理流程 | 文件已生成 |
| 状态查询成功,正文为运行中 | 最近一次查询时仍未完成 | 查询200,所以任务成功 |
| 操作进入失败终态 | 后台处理失败,附可公开的原因 | 再查一次状态就会重新执行 |
| 操作成功,返回结果标识 | 服务报告结果已产生 | 结果一定属于本次请求且内容合格 |
| 结果身份与验收项通过 | 本次目标在已检查范围内完成 | 可以跳过发布、发送等后续授权 |
这张表是本文的工程拆解,不是新的HTTP标准。
二、跟一遍目录生成:把“等结果”做成可恢复状态
以下目录、状态与字段均为虚构教学设计,未执行模型、目录服务、真实网络请求或Agent框架。
用户要求:“把这批已授权文件整理成目录,只保存草稿,不要公开。”任务约束包含输入清单版本 batch-v7,以及“不要公开”。
第一步:提交一次创建请求,保存关联。 假设服务受理后返回操作名 operations/catalog-47。运行层至少保存:本地任务标识、输入清单版本、操作名、受理时间、当前已知状态、下次允许查询的时间,以及结果验收条件。操作名是远端追踪句柄,不是目录文件ID;它也不天然授予读取权限。
第二步:后续查询这个操作,而不是再次创建。 状态先是排队中,后来变为运行中。这里拿到的都是追踪信息,不该触发“目录已完成”的通知。即使模型换了会话,恢复入口也应是“读取已有操作”,而不是根据聊天摘要重新提交。
第三步:分开处理终态。
- 如果失败,保留操作名和明确原因,判断是补充输入、修正配置,还是需要新的可信指令。轮询旧操作不是重做任务。
- 如果成功,取得结果文件标识,核对其与本次操作、输入版本的关联,再检查可读取性与目录覆盖情况。
- 如果目录只包含部分文件,不能把接口成功包装成“整批完成”;应按预先定义的验收规则交付部分结果和缺口,或判为未达标。
第四步:完成也不自动公开。 操作成功只意味着生成阶段结束。用户的“只保存草稿”仍然有效,结果查询和内容验收不会增加发布权限。
Google AIP-151对错误传播的区分也值得借用:阻止操作启动的错误直接返回;执行阶段的失败放在操作的错误字段中;非终态错误可以出现在元数据中。[3] 适配层如果把这些都压成一个布尔值,恢复动作就很容易选错。
三、别把三个时钟设成同一个
长任务里至少有三种等待边界:
- 单次I/O时限。 一次提交或状态查询,最多等多久得到响应。
- 业务操作期限。 后台任务按服务契约允许执行多久,可能由服务端限制。
- 本轮观察预算。 Agent这次最多花多少时间或多少次读取来等待结果。

留下你的想法 0
欢迎提问、补充和不同观点。评论通过审核后会公开显示。