Ctrl K
ComunidadGuías…

docs/MODEL_CONTINUATION.md

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
# 长任务续跑与原请求恢复

[English](MODEL_CONTINUATION.en.md)

模型每次生成有输出预算;宿主 Agent 的整项任务可以由多次模型调用和工具操作组成。合理预算与自动续跑相互配合,不能靠取消边界、无条件放大预算或重复整项任务解决截断。此文使用现有 `bailing.model-operation.v1`、`bailing.model-stream.v1` 与 `bailing.provider-response.v1`,不新增续跑接口或私有结束字段。

## 中枢和宿主的边界

中枢按服务配置派发一次模型请求,透传原生供应商 JSON/SSE,将原响应、用量与派发证据保存到原 `operation_id`。`orchestration=host` 表示任务循环、模型语义解析、工具执行、检查点与用户体验由客户端宿主管理。中枢不因 `length`、缺少正文、HTTP 错误或未知供应商结束原因自动再次 POST,不切换模型、协议或凭据。

`result_state=complete` 只表示原供应商响应交换已保存。回答是否完整、工具参数是否完整、整项任务是否完成,是不同的宿主判断;`billing_state=pending` 也不是阻止宿主使用已保存响应的理由。单次超时、输入字节、上下文窗口、服务输出上限和账户额度保持各自边界,不能用续跑绕过。

## 两条互斥路径

| 已确认的状态 | 宿主动作 |
| --- | --- |
| 最终原 operation 回执可用,供应商适配器明确识别输出预算截断 | 保存原部分内容和检查点;在原任务授权内准备新续段,以新的 operation 调用模型 |
| 模型 POST 丢失 ACK、流缺少最终 operation 帧、网络或持久化结果未知 | 先按原 operation 查询,只恢复已保存结果;不新建 ID 重发生成 |
| 原 operation 尚在 pending | 等待或查询原 ID,不并发生成替代请求 |
| 正常结束,或供应商说明为内容过滤、拒绝、未知结束原因 | 由适配器按原生语义处理,不猜测可以自动续跑 |
| 已取消、授权终止、原响应过期且本地无可信副本 | 停止自动续跑,保留证据并呈现需要处理的原因 |

只有供应商适配器明确识别的输出预算结束原因才能进入截断路径。例如适配器已支持的 `finish_reason=length` 可以作为证据;未知的扩展值不能靠字符串猜测。`outputTokens` 恰好等于预算、答案很短、HTTP 正常 EOF、计费完成或 SSE `[DONE]` 均不能单独证明任务完成,也不能单独授权自动续段。某些模型把思考包含在总输出预算中,预算解释遵循[模型输出预算契约](MODEL_OUTPUT_BUDGET.md)。

查询原 operation 与重复原 POST都受既有幂等约束保护,但恢复应优先调用只读查询。相同 ID 的不同内容是冲突,不能用改参数、补上下文或换模型修改已保存的意图。查询返回未找到也不是“已证明没有执行”的授权;恢复缺口需保留并处理。

## 宿主续段检查点

在发起下一段之前,宿主应持久保存任务、原 operation、选定服务与描述修订、规范化结束原因、已输出片段、工具调用结果以及已完成和未完成步骤。新续段使用新 operation,以明确的父子关联保存在宿主本地;本轮协议不增加父 operation 字段。

续段上下文携带已经保存的有效内容与工具结果,要求从未完成步骤接续。不要把原始用户请求重新当作尚未执行的新任务,也不要重发先前模型请求。模型本轮的原生工具调用和工具结果必须保持供应商消息格式及关联标识。针对可见回答的分段展示和重复前缀,可在宿主呈现层合并;不能篡改原响应、摘要或工具结果证据。

自动续跑需要有限的连续续段数、累计任务时间/费用或 Token 预算、循环和无进展检测,并允许用户随时取消。默认值由宿主结合其现有任务政策配置,不能无界递归;达到边界时保留检查点,以简洁原因和下一步动作代替反复要求用户手工输入“继续”。上下文接近窗口时,按宿主已有可恢复摘要机制处理,保留原 action 与结果引用,不能通过摘要丢失去重或审批证据。

客户端重启、断网恢复和重复流回放也必须复用同一检查点,避免同时开启两个续段。只收到流中的截断终止片段而未收到最终 operation 回执时,先恢复原 operation,再决定新续段。用户取消或任务结束之后的晚到结果不得重新启动循环。

## 工具执行不能随文本重跑

模型 operation 的幂等只能防止同一模型请求重复派发,不能识别“模型在下一段用新 ID 重复提出同一笔业务操作”。宿主须持久化业务 action 与原 `invocation_id`、输入摘要、审批及结果的关联,并将结果带入续段。仅凭新 `tool_call_id` 或参数相同,不能证明新的业务写入已获得授权;也不能跨任务把所有相同参数一律去重。

截断响应中出现的工具调用,即使局部参数恰好能解析为 JSON,也不能直接执行。等待供应商适配器确认完整的工具调用结束语义,并经过原能力 schema、授权、审批和幂等流程。残缺参数不能通过自动补全后当作原调用执行。

- 对已完成 invocation,复用原回执和结果,不创建新 invocation 重做。
- 对执行不确定或 `reconciliation_required` 的 invocation,先只读检查原调用,不能通过续段重试写入。
- Agent 客户端 SDK 的 `inspectInvocation()` 对应只读原 invocation receipt;它不消费审批,也不触发业务派发。
- Agent 客户端 SDK 的 `resume()` 可能在原调用审批通过后执行其首次业务派发,不能把它用作轮询或只读检查。只有原状态和原任务授权明确允许时,才能在原 invocation 上继续既有流程。

这些约束不替代业务系统自己的幂等和授权,中枢不宣称跨所有外部系统的业务副作用 exactly-once。

## 验证与限制

`provider-stream.test.ts` 验证 JSON/SSE 的明确截断、中文、多字节正文、思考用量及残缺工具参数的原文保留。`model-continuation.test.ts` 使用真实网关逻辑和合成持久化/报价端口验证:截断交换保持 complete、原 ID 恢复和重复请求不再派发、冲突意图拒绝、新续段单独派发、真实传输未知不自动重试。合成端口不构成数据库事务、真实供应商、客户端持久化或业务工具执行验收。

真实客户端还需验证:续段次数边界、无进展退出、取消、崩溃重启、多窗口竞争、上下文摘要、已完成工具复用和不确定写入核对。仅部署中枢不会自动赋予客户端上述任务循环能力。