深度分析长期agent执行中上下文积累的问题:临时数据变成持久输入、相关性衰减、决策复杂度上升,提供设计启示。
一个用于说明问题的报告 Agent 正在准备月度运营复盘。它查询财务系统、CRM、客服系统和数据仓库;对比本月与此前各期的数据;调查重大变化;起草说明;收集各负责人意见;并在数天内多次修订报告。
到了第三次修订时,它的 context 中已经包含原始查询结果、被弃用的假设、重复的指令、负责人此前的意见,以及当前版本的草稿。此时,最重要的一项修正——财务负责人否定了最初的收入解释——不得不与此前积累的所有内容争夺注意力。
这个 Agent 并不是智能不够用了。它积累了 context debt:原本临时性的执行材料,变成了永久性的推理输入。
把所有中间结果都保留在模型的 context 中,似乎很安全,因为不会丢失任何内容。但在实践中,随着运行时间增长,信息的相关性会不断下降:
大型工具响应会消耗大量 token;
旧指令会与较新的决策发生冲突;
重复总结会引入细微偏差;
已被否定的假设仍与确认采纳的结论紧密混杂;以及
当前交付物会越来越难以与早期草稿区分。
更大的 context window 只能延缓这个问题。它无法定义哪些状态具有权威性、哪些证据可以恢复,也无法决定哪些决策应当在系统重启后继续保留。
一个长时间运行的工作流至少需要四种存储角色。
当前目标、即时约束、筛选后的证据,以及下一步可执行操作,应该保留在这里。这个集合应当足够小,确保其中每一项都能影响下一次决策。
已经完成的 checkpoint、负责人、审批结果、截止时间、未解决的异常,以及允许执行的后续操作,都应该存放在 prompt 之外。这些状态必须能够跨越模型调用、worker 重启和任务交接而持续存在。
原始数据源结果应当与稳定标识符、时间戳和访问控制信息一同保留。后续步骤需要检查这些结果时,Agent 可以重新加载,而不必把每条记录都注入每一个 prompt。
当前的报告、计划、工单或其他业务产物,需要拥有独立的版本历史。评审者提出的修改应当直接更新这一产物,而不是让整段对话记录成为唯一能够反映变更内容的载体。
把材料移出 prompt 并不等于删除,而是把信息放到合适的位置,让 runtime 能够按需、有意识地取回。
通用的对话摘要或许能保留主题,却可能丢失真正重要的操作事实:是谁否定了某项解释、哪个数据源取代了原来的依据,以及这项修正只适用于某个指标,还是适用于整份报告。
有效的 checkpoint 应该采用结构化形式。例如:
{
"task_id": "monthly-review-2026-07",
"objective": "Produce an approved operating review",
"checkpoint": "finance-variance-reviewed",
"accepted_findings": [
{
"metric": "net_revenue_retention",
"explanation": "Two enterprise downgrades",
"evidence_refs": ["warehouse:q_184", "crm:acct_72"]
}
],
"rejected_findings": [
{
"explanation": "FX movement",
"rejected_by": "finance-owner",
"decided_at": "2026-08-03T09:20:00Z"
}
],
"open_questions": ["Confirm support-cost allocation"],
"allowed_next_actions": ["analyze_support_costs", "request_owner_review"]
}
具体 schema 会因场景而异。关键在于把决策与产生这些决策的 token 分离开来。
每个 checkpoint 都应该回答以下问题:
哪些内容继续留在模型 context 中?
哪些内容转移到持久状态?
哪些原始证据可以在之后恢复?
在当前状态下,哪些操作是有效的?
Compaction、子任务隔离和渐进式加载指令,都是落实这些选择的机制。它们无法替代状态模型。
报告工作流可以把财务差异分析、销售 pipeline 变化和客服请求量分析拆分开来。每个子任务只接收与自身工作相关的系统、定义和时间范围。
隔离可以减少相互干扰,但也会带来集成问题。如果三份经过精心润色的叙述采用了不同的定义,负责协调的 Agent 就无法安全地对它们进行整合。
共享的结果契约可以要求每个子任务返回:
指标标识符和报告周期;
当前值和对比值;
解释和置信度;
权威数据源引用;
尚未解决的问题;以及
请求作出的决策或审批。
这个契约的作用不只是改善格式。它为协调者提供了稳定的边界,用于验证、比较和重试。
如果某个子任务失败,runtime 可以只重新运行这个单元,而无须重放整个工作流。如果评审者修正了某项指标定义,系统也可以只将依赖该定义的结论标记为失效。
长时间运行的 Agent 应该从 checkpoint 开始接受测试,而不能只测试从头运行的情况。
恢复运行时,runtime 应当能够重建:
当前目标以及已确认接受的交付物版本;
已完成和待完成的步骤;
当前负责人和截止时间;
最新的权威决策;
下一步所需的证据引用;以及
仍然有效的权限。
最后一项尤其重要,因为工作流暂停期间,授权可能发生变化。昨天已获批准的任务,Agent 今天真正执行时,可能需要重新检查权限。
因此,恢复测试不只是加载一个已保存的 prompt。它需要验证工作流能否根据持久状态,重新构建出最小且可信的工作集。
外部状态会带来存储、保留期限和访问控制方面的决策。Compaction 可能遗漏后来变得重要的细节。子任务隔离会增加编排复杂度。重新加载证据可能增加延迟。
这些都是可以衡量的权衡。值得关注的指标包括:
工作流各阶段的 context 大小;
对同一证据的重复检索次数;
评审者对 compaction 结果的修正次数;
从 checkpoint 恢复运行的失败次数;
重启后使用过期决策的情况;
证据重新加载的延迟;以及
每份已接受交付物的成本。
有些工作应该暂停,而不是进行 compaction。如果评审者从根本上改变了目标,那么创建一个新版本并进行明确交接,可能比要求 Agent 重新解读一段漫长且相互矛盾的历史记录更安全。
最终完成的报告应当保留报告周期、指标定义、评审者决策、证据引用和尚未解决的注意事项。下个月的 Agent 可以使用已经验收的产物进行对比,而不必继承生成这份产物时留下的所有执行残骸。
当系统把记忆与堆积混为一谈时,context debt 就会出现。长时间运行的 Agent 需要的是持续维护的工作集和持久可靠的运行记录,而不是一个永无止境地膨胀的 prompt。
在长时间运行的 Agent 中,你是如何将工作 context 与持久任务状态分离的?
本文由《Long-Running Agents Accumulate Context Debt》改编而来,原文由 Coryntas 发布,并针对 DEV 社区进行了调整。
如需采取进一步措施,你可以考虑屏蔽此人和/或举报滥用行为。