长任务续跑:从摘要压缩到分层状态管理
作者:很菜不狗2026.11.10 14:39浏览量:0简介:以编程智能体迁移认证中间件这类长任务为例,拆解上下文窗口耗尽后的三种处理思路:摘要压缩、窗口切换与分层状态存储。文章说明工作集、交接笔记、历史记录和外部事实各自承担什么职责,并给出示意流程与常见失败场景的应对办法,帮助开发者设计可靠的长任务续跑方案。
一、长任务为什么会断在上下文上
编程智能体处理跨模块任务时,会持续累积对话内容、文件片段、工具调用输出和测试日志。模型的上下文窗口有固定上限,任务进行到一定阶段,窗口就会接近满载。这时系统只有三种选择:丢弃最早的内容、压缩已有内容,或者开启新窗口并把必要信息带过去。前两种都会损失信息,第三种的关键在于带过去什么。
以一个典型任务为例:把一套跨模块的认证中间件迁移到新接口。智能体先梳理调用链,确认旧接口在兼容期内不能删除。随后,它排除了统一升级依赖库的路线,改为在中间件层做适配。主链路改完后,集成测试出现偶发的鉴权失败。此时任务远未完成,窗口却快满了。
二、摘要压缩的局限
传统做法是让模型把前文压缩成一份更短的摘要,然后带着摘要继续工作。这种方法实用,许多长任务因此得以继续推进。但它要求摘要在写出时就预测后续会用到什么,而这个预测常常失准,主要表现为三类问题。
- 结论保留,依据丢失。 摘要写了“旧接口需保留”,却没有写明兼容的具体原因。之后有人想删除接口时,智能体无法判断原来的前提是否仍然成立。
- 现象保留,证据丢失。 摘要写了“集成测试偶发失败”,首次失败时的完整日志、堆栈和时间点却没有保留。复现时只能从头排查。
- 否定路径丢失。 某条方案已经验证不可行。如果放弃原因被压缩掉,新窗口中的智能体可能重新尝试同一条路线,白白消耗时间和上下文。
摘要要同时承担“当前进度”“决策依据”“失败记录”三种职责。压缩得越狠,三者越容易顾此失彼。
三、把状态拆到不同载体中
更稳妥的思路是承认不同信息的生命周期不同,分别存放。可以划分为四类载体。
- 工作集(working set)。 当前窗口中正在使用的信息,例如正在编辑的函数、刚读到的配置片段。它追求精简,窗口切换后即可丢弃。
- 交接笔记(notes)。 结构化的任务状态,记录目标、已完成步骤、已排除方案及原因、未决问题。笔记本身很短,但每一条都附带依据,是跨窗口交接的主要载体。
- 历史记录(history)。 完整的原始对话与工具输出,按轮次编号、可检索。它不默认进入上下文,只在需要回查时按条目读取。
- 外部事实(external facts)。 代码仓库、版本记录、测试系统、工单和日志平台中的真实状态。这些内容本来就存在于系统之中,智能体只需记录引用,无需复制全文。
四类载体的职责边界要清楚。工作集回答“眼前要用什么”,笔记回答“接下来做什么、为什么这样做”,历史记录回答“当时到底发生了什么”,外部系统回答“现在的真实状态是什么”。
四、窗口切换的基本流程
窗口切换可以拆成四步:写入交接笔记、记录历史锚点、开启新窗口、载入笔记并按需回查。下面的示意代码只说明状态流转,不对应任何具体接口。
# 示意代码:说明状态如何在窗口之间流转def hand_off(task, window):notes = {"goal": task.goal,"done": task.completed_steps,"ruled_out": [{"approach": a.name, "reason": a.reason, "evidence_ref": a.evidence}for a in task.rejected_approaches],"open_questions": task.open_questions,"external_refs": task.external_refs, # 提交号、工单编号、日志位置"history_anchor": window.last_turn_id, # 指向历史记录中的位置}store.save_notes(task.id, notes)return new_window(system_prompt=task.base_prompt, notes=notes)def resume(task_id, new_window):notes = store.load_notes(task_id)# 工作集只放入笔记摘要,细节按需回查return new_window.bootstrap(notes)def recall(task_id, query, history_store):# 按关键词或轮次检索原始记录,只取有限条数的片段return history_store.search(task_id, query, limit=5)
代码里有三个设计要点。第一,每条“已排除方案”都带有证据引用,新窗口能看到放弃的理由。第二,笔记里保存的是历史锚点,而不是历史全文,工作集不会因此膨胀。第三,回查接口限定条数,避免一次检索就占满窗口。
五、各类载体的读写规则
规则定得清楚,才能避免载体之间互相污染。
- 笔记只写结论和依据,不写过程流水账。 每条“已排除方案”必须带原因和证据引用,每个未决问题必须说明阻塞点。
- 历史记录只追加,不改写。 回查结果可信,依赖于原始记录未被修改。
- 外部事实以引用形式进入笔记,读取前需要重新校验。 代码和环境可能在窗口切换期间已经变化,笔记中的状态只能作为线索。
- 工作集设上限。 超出部分优先通过回查历史获取,而不是长期常驻于上下文中。
六、常见失败场景与应对
- 笔记漏写,恢复后重复已完成步骤。 应对办法是以外部状态为准。恢复后先比对代码版本与测试结果,再决定从哪一步继续。
- 证据引用失效,历史记录被清理或外部日志过期。 应对办法是写入笔记时同时保存关键片段的摘录,而不只保存指针。
- 过度回查,每次都翻阅历史,窗口很快被填满。 应对办法是限制单次回查的条数,并要求先用笔记判断是否真的需要回查。
- 笔记与现实不一致。 例如笔记记录测试已通过,但代码在之后又被修改。应对办法是在恢复阶段重新执行关键校验,不直接信任笔记中的结论。
七、落地建议
- 优先结构化“已排除方案”和“未决问题”。这两类信息最能减少重复劳动。
- 在任务开始时写明完成条件,并记入笔记。新窗口据此判断是否已经收尾。
- 交接前后对状态做快照比对,检查笔记是否覆盖了关键信息。
- 评估方案时,用真实的长任务做回放测试。统计重复尝试次数、回查次数和最终完成率,比只看摘要长度更能说明问题。
上下文窗口会继续变大,但长任务的可靠性更多取决于状态如何组织。把临时信息、交接依据、原始记录和外部事实分开存放,每类载体各司其职,比让一份摘要承担全部责任更可控。

登录后可评论,请前往 登录 或 注册