1. 为什么长任务里的 AI Agent 总是跑着跑着就偏了做过 AI Agent 落地的人大概率都遇到过这种场景一个原本设计得很清晰的任务比如“帮我调研某个行业近三年的技术演进路线输出一份带引用的报告”Agent 前几步干得挺漂亮搜索、筛选、整理结果跑到第七八步的时候它开始重复劳动、忘记最初的目标、把中间某个假设当成了既定事实最后交出来的东西跟你要的完全不是一回事。你回头去看它的执行日志会发现它不是“笨”而是在某个节点上把上下文搞丢了或者被一堆无关信息淹没了。这个问题的核心其实不在模型本身而在上下文工程。所谓上下文工程就是你怎么组织、裁剪、传递和刷新 Agent 在长任务中每一步所看到的“信息环境”。它跟提示词工程不是一回事提示词工程关心的是“这一句话怎么说”上下文工程关心的是“这一整条任务链上每一步该让模型看到什么、忘掉什么、记住什么”。长任务之所以容易跑偏本质上是三个原因叠加上下文窗口有限但任务信息无限增长、中间步骤产生的噪声会污染后续决策、目标在多次传递后被稀释或改写。我拿一个具体的模拟项目来说。假设你要做一个“竞品分析 Agent”任务链路大概是确定竞品范围 → 逐个抓取公开信息 → 提炼每个竞品的核心功能 → 横向对比 → 输出结论。这条链路有 5 到 8 个主要步骤每个步骤又可能拆成多次模型调用。如果每一步都把前面所有原始信息一股脑塞进去到第四步的时候上下文里已经堆了几万字的原始素材模型要在里面找“我到底在对比什么维度”注意力被严重分散。实测下来这种“全量堆叠”的做法在超过 6 步的任务里目标偏离率会明显上升。所以这篇内容我想聊的就是怎么用 4 个具体方法把长任务的上下文管住让 Agent 跑得远还不跑偏。适合正在做 Agent 应用开发、任务编排、自动化流程的从业者参考也适合刚接触这块、想搞清楚“为什么我的 Agent 一长就废”的朋友。下面我会把每个方法的原理、适用场景、具体操作和踩过的坑都讲清楚你基本可以照着抄。2. 方法一分层记忆结构把“当前任务”和“历史档案”分开2.1 为什么不能把所有信息都塞进一个上下文很多人做 Agent 的第一反应是“上下文窗口不是挺大吗那就都放进去”。这个思路在短任务里没问题但长任务里会出大问题。原因有两个第一注意力稀释。模型在处理长上下文时并不是均匀地关注每个 token中间部分的信息容易被忽略这在业界被称为“lost in the middle”现象。第二噪声累积。每一步产生的中间结果里有大量是过程性的、临时的比如某次搜索返回的无关段落、某个被否决的假设这些东西留在上下文里会在后续步骤里被模型误当成有效信息。我做过一个对比测试同一个 8 步任务方案 A 是每步都把全部历史塞进去方案 B 是只保留“当前步骤所需信息 一份精简的任务档案”。结果方案 A 在第 6 步开始出现目标漂移方案 B 跑完全程目标一致性明显更好。这不是模型能力问题是信息组织问题。2.2 三层记忆的具体划分方式我的做法是把上下文分成三层每层职责明确任务层Task Layer只放最核心的东西——任务目标、当前步骤编号、本步骤的输入和输出要求。这一层要极简通常控制在几百字以内。它是 Agent 每一步都要看的“当前指令”。档案层Archive Layer放已经完成步骤的结构化摘要不是原始内容。比如“第 2 步已完成竞品 A 的功能提炼结论是 X/Y/Z 三项”而不是把抓取的两千字原文放进来。这一层是 Agent 的“长期记忆”按需检索。工作层Working Layer放当前步骤正在处理的原始素材比如这次搜索返回的内容、这次要分析的文档。这一层是临时的步骤结束后就压缩进档案层原始内容丢弃。这样分的好处是Agent 每一步看到的上下文是“任务指令 相关历史摘要 当前素材”而不是一锅粥。任务目标始终在最显眼的位置历史信息以压缩形式存在噪声被挡在工作层之外。2.3 摘要怎么写才不会丢关键信息档案层的摘要质量直接决定方法一是否有效。我踩过的坑是一开始让模型自由发挥写摘要结果它把关键数字和结论都省了只留下“完成了分析”这种废话。后来我固定了摘要模板强制包含四个要素步骤编号、本步结论、关键数据/事实、对后续步骤的影响。举个例子一个竞品分析步骤的摘要应该是这样步骤 3竞品 B 功能提炼 结论竞品 B 主打轻量化核心功能为 A/B/C 三项 关键数据定价 99 元/月用户量约 50 万来源公开报道 对后续影响对比维度需增加“定价策略”一项这种结构化摘要既压缩了信息量又保证了后续步骤能拿到关键事实。实测下来用固定模板的摘要比自由摘要后续步骤的信息召回准确率高出不少。注意摘要模板不要设计得太复杂四个要素足够了。要素太多模型会为了填满模板而编造内容反而引入错误信息。3. 方法二动态上下文裁剪按“相关性”而不是“时间顺序”保留信息3.1 时间顺序保留法的致命缺陷大部分 Agent 框架默认的上下文管理是“滑动窗口”或者“保留最近 N 轮”本质上是按时间顺序保留。这在对话场景里够用但在长任务里很危险。因为长任务的关键信息不一定在最近几步——任务目标可能在第一步核心约束可能在第三步而最近几步可能只是在做格式整理这种边缘工作。如果按时间裁剪很可能把最关键的目标信息裁掉了留下的是最近的琐碎操作。我遇到过一个典型 case一个数据处理 Agent任务要求“输出必须保留两位小数且不能有负值”。这个约束在第一步就给了结果跑到第十步做汇总时Agent 输出了负数和一堆小数位。排查发现滑动窗口把第一步的约束挤出去了。这就是按时间裁剪的锅。3.2 相关性打分的实操做法我的解法是引入一个轻量的相关性打分机制。具体做法是在每次组装上下文之前对候选信息片段历史摘要、原始素材、约束条件等打一个相关性分数分数由两部分组成——与当前步骤的语义相似度信息类型权重。信息类型权重是我手动设定的比如信息类型权重说明任务目标与约束1.0永远最高优先级不参与裁剪当前步骤指令0.9必须保留上一步结论0.7通常相关早期步骤摘要0.5按相似度决定原始素材0.3仅当前步骤相关时保留语义相似度可以用一个轻量嵌入模型算把当前步骤的描述和候选片段做向量比对。最终得分 相似度 × 类型权重按得分排序取前若干条塞进上下文。这样既保证了目标和约束永远在又让历史信息按实际相关性动态进出。3.3 裁剪的边界哪些信息绝对不能裁动态裁剪有个红线任务目标和硬性约束永远不参与裁剪。这两类信息必须无条件保留在上下文里哪怕它们跟当前步骤看起来不相关。因为长任务里约束往往是在最后几步才被违反的如果中途裁掉了到后面就没人记得了。我的做法是把目标和约束单独拎出来放在任务层的最前面并且用固定格式标记比如[任务目标] 输出一份带引用的行业技术演进报告 [硬性约束] 1. 必须标注来源 2. 时间范围近三年 3. 不接受推测性内容这样无论上下文怎么裁剪这几行永远在。实测下来这个简单的做法能挡掉相当一部分“跑偏”问题。实操心得约束条件最好在每一步的输出校验里也检查一遍不要只靠上下文保留。双保险比单保险稳。4. 方法三阶段性上下文刷新主动“重启”而不是被动累积4.1 为什么长任务需要主动刷新即使做了分层和裁剪上下文还是会随着步骤增加而缓慢膨胀。因为每一步都会往档案层加摘要加着加着档案层本身也变长了。这时候就需要一个主动刷新机制在任务的某些节点上把当前所有信息重新压缩一遍生成一份新的“任务状态快照”然后用这份快照替换掉之前的累积上下文。这有点像电脑用久了要重启不是因为它坏了而是因为累积的临时状态太多重启一下回到干净状态。Agent 的上下文刷新也是同理目的是消除累积噪声重新对齐目标。4.2 刷新节点的选择什么时候该刷新刷新不能太频繁否则会丢失细节也不能太少否则噪声累积。我的经验是选在任务的自然阶段边界上刷新。什么叫自然阶段边界就是那些“一个子目标完成、下一个子目标开始”的节点。比如竞品分析任务里“信息收集阶段结束、对比分析阶段开始”就是一个刷新点。具体判断标准可以看这几条当前步骤的产出是一个完整的、可独立成立的结论下一步的任务类型跟当前步骤有明显差异比如从“收集”转到“分析”上下文长度超过了某个阈值我一般设在窗口的 60% 左右满足其中两条就可以触发一次刷新。4.3 刷新时保留什么、丢弃什么刷新的核心动作是把累积的档案层重新压缩成一份状态快照。快照内容包含任务目标与约束原样保留已完成阶段的核心结论压缩成要点当前进度和下一步计划已知的关键事实和数据丢弃的是过程性日志、被否决的假设、重复的素材、已经消化进结论的原始内容。刷新后上下文长度通常会降到原来的三分之一甚至更低但关键信息一个不少。我实测过一个 12 步的任务中途刷新两次最终输出的目标一致性比不刷新的版本好很多而且因为上下文短了每一步的响应速度也更快。注意刷新动作本身也是一次模型调用要给它明确的指令比如“请把以下任务历史压缩成一份状态快照保留目标、约束、核心结论和关键数据丢弃过程细节”。指令不明确的话模型可能压缩过度把关键数据也丢了。5. 方法四外部化状态存储让 Agent 学会“查笔记”而不是“背全书”5.1 上下文不是存储别让它干存储的活前面三个方法都是在“怎么把上下文管好”的框架里打转但还有一个更根本的思路有些信息根本不该放在上下文里应该放到外部存储需要的时候再查。这就像人做复杂项目不会把所有资料背在脑子里而是放在笔记本和文件柜里需要时翻一下。Agent 也一样。长任务里会产生大量结构化信息——抓取的素材、中间结论、数据表、引用来源。这些东西全塞上下文既占地方又容易造成噪声。更好的做法是建一个外部状态存储把信息按结构存进去上下文里只保留“索引”和“查询能力”。5.2 外部存储的三种常见形态根据任务类型不同外部存储可以选不同形态键值存储适合存结构化的中间结论比如{竞品A: {功能: [...], 定价: ...}}。Agent 需要时按 key 查。向量库适合存非结构化的素材比如抓取的文档段落。Agent 用语义检索找相关内容。文件系统/表格适合存需要人工检查或后续处理的数据比如生成的对比表、引用列表。我一般会组合使用结论用键值存储素材用向量库最终产出用文件。上下文里只放一个“存储索引”告诉 Agent“你需要什么信息可以去哪里查”。5.3 让 Agent 主动查询的提示设计外部化存储的关键是让 Agent 知道“什么时候该查、怎么查”。这需要在系统提示里明确写清楚存储的结构和查询方式。比如你可以访问以下外部存储 - 竞品结论库键值按竞品名称查询已提炼的功能和定价 - 素材库向量检索按语义查询原始文档段落 - 产出目录文件存放已生成的中间产物 当当前上下文缺少必要信息时优先查询外部存储而不是凭记忆推测。最后一句很重要。如果不明确说“优先查询”模型倾向于用上下文里残存的信息硬编容易出错。加上这句之后Agent 在信息不足时会主动去查而不是瞎猜。5.4 外部化带来的额外好处可审计、可复用外部化状态还有个隐藏好处整个任务的中间状态是可审计、可复用的。上下文里的信息任务结束就没了但外部存储里的结论和素材可以留下来下次做类似任务时直接复用。我做过一个系列调研任务第二次做同类分析时直接复用了第一次的竞品结论库省掉了大量重复工作。实操心得外部存储的 schema 要提前设计好不要边做边改。schema 一改之前存的索引就对不上了Agent 查询会失败。我一般会在任务开始前先把存储结构定下来哪怕一开始字段少一点后面再加也比中途改强。6. 四个方法怎么组合使用一套可落地的上下文工程方案6.1 组合策略分层打底裁剪动态调刷新定期做外部化兜底这四个方法不是互斥的实际项目里我通常是组合使用。一个比较稳的组合方式是分层记忆作为基础架构任务层、档案层、工作层三层固定下来动态裁剪在每次组装上下文时执行按相关性决定档案层和工作层放什么阶段性刷新在任务阶段边界触发压缩档案层重置上下文外部化存储作为兜底所有不适合放上下文的信息都往外部存Agent 按需查询这套组合下来上下文长度能稳定控制在一个合理范围同时关键信息不丢。我拿一个 15 步的模拟调研任务测过不管理上下文的版本在第 9 步左右开始明显跑偏用这套组合的版本跑完全程目标一致性保持得不错。6.2 一个具体的上下文组装伪代码为了让你更直观地理解我写一段伪代码展示每次模型调用前上下文是怎么组装的def build_context(task, current_step, archive, working, external_store): # 1. 任务层永远保留 context [ f[任务目标] {task.goal}, f[硬性约束] {task.constraints}, f[当前步骤] {current_step.description} ] # 2. 档案层按相关性裁剪 candidates archive.get_summaries() scored [(s, relevance(s, current_step) * weight(s.type)) for s in candidates] top_summaries [s for s, score in sorted(scored, reverseTrue)[:5]] context.extend(top_summaries) # 3. 工作层当前步骤素材 context.extend(working.get_current_materials()) # 4. 外部存储索引 context.append(f[可用外部存储] {external_store.get_index()}) # 5. 检查是否需要刷新 if should_refresh(current_step, context): context refresh(context) return context这段伪代码的核心逻辑就是目标约束永远在历史按相关性进素材按需进外部存储给索引该刷新时刷新。你可以根据自己的框架调整具体实现但思路是通用的。6.3 效果评估怎么知道上下文工程做得好不好做完这些怎么判断效果我一般看三个指标指标含义好的表现目标一致性最终产出与原始目标的匹配度高且不随步骤增加明显下降上下文长度每次调用的平均 token 数稳定不随步骤线性增长重复劳动率同一步骤被重复执行的次数低说明状态管理清晰这三个指标不需要很精确的测量人工抽查几步就能看出趋势。如果目标一致性随步骤明显下降或者上下文长度一路飙升说明上下文工程还有优化空间。7. 常见问题与排查技巧实录7.1 摘要越写越长档案层反而膨胀了这是很常见的问题。原因是摘要模板没约束长度模型倾向于写详细。解法是给摘要设硬性字数上限比如每条摘要不超过 150 字超了就让模型重写。另外可以定期对档案层做二次压缩把多条相关摘要合并成一条。7.2 动态裁剪把关键信息裁掉了如果发现 Agent 突然“忘了”某个重要约束先检查裁剪逻辑是不是把约束也纳入打分了。约束和目标必须走白名单不参与裁剪。另外相关性打分的权重表要定期 review有时候是权重设错了导致某类信息总被裁。7.3 刷新之后 Agent 丢失了细节刷新压缩过度是常见坑。解法是在刷新指令里明确列出“必须保留”的字段比如关键数据、引用来源、未解决的疑问。另外刷新后可以加一步校验让 Agent 确认“目标、约束、核心结论是否都在”不在就补。7.4 外部存储查询失败或查不到通常是 schema 不匹配或者索引没更新。排查顺序先看存储里到底有没有这条数据再看索引是否指向正确位置最后看 Agent 的查询语句是否符合 schema。我一般会在外部存储层加一个简单的日志记录每次查询的输入和结果出问题直接看日志最快。7.5 四个方法都用了还是跑偏如果都用了还跑偏大概率不是上下文问题而是任务拆分本身有问题。检查一下任务步骤是不是粒度太粗或者步骤之间的依赖关系没理清。上下文工程能解决“信息组织”问题但解决不了“任务设计”问题。有时候把一个大步骤拆成两个小步骤问题就消失了。最后分享一个我常用的小技巧在任务开始时让 Agent 自己复述一遍任务目标和约束并确认理解。这一步花不了多少 token但能提前暴露理解偏差。如果它复述出来的目标跟你的预期不一致当场就能发现不用等到跑偏了才回头查。这个习惯帮我省了很多调试时间。
阅读完成 · 觉得有帮助?