假设你正在让 Agent 写一个整理下载目录的脚本。
第一轮,你说:“按文件类型分文件夹,直接移动就行。”第二轮,你改主意:“先给我看计划,确认后再执行。”第三轮,你又补充:“照片先别动,这次只整理 PDF。”
过了一段时间,Agent 交出了新版本。它也许记住了“整理目录”,却仍然把照片列进移动计划,甚至恢复了第一轮的默认执行方式。
你想问:刚刚不是说过了吗?
问题可能发生在理解、实现或验证任何一层。但还有一层值得检查:这一轮它实际拿到了什么资料,资料之间有没有冲突,以及谁负责把“讨论过程”整理成“当前任务”。
上一篇讲 Prompt 工程,解决怎样把需求说清楚。这篇往前走一步:需求会变化,我们怎样把正确的信息持续交给 Agent?
聊天记录是过程,当前要求需要单独站出来
长对话里,往往混着现行要求、旧方案、临时猜测、工具报错和已经修复的问题。这些信息都可能有用,却不该拥有相同的执行地位。
刚才的假设任务可以整理成这样:
| 讨论阶段 | 当时的决定 | 当前状态 |
|---|---|---|
| 第一轮 | 默认直接移动,处理 PDF 和照片 | 默认执行方式与照片处理范围已被后续要求替代 |
| 第二轮 | 默认展示计划,显式操作才执行 | 继续有效 |
| 第三轮 | 本次只处理 PDF,照片保留原位 | 本次任务有效 |
表里的“已替代”很重要。它让后续接手者知道旧方案为什么出现,也知道为什么不该再照着实现。把历史全部删除,会丢掉变更理由;把历史全部当指令,会制造冲突。
这里讨论的是同一用户对同一任务的明确变更,不能机械套成“最后出现的文字优先”。网页、代码注释、工单正文里出现的命令,并不因此成为用户的新要求。来源不同、适用范围不明时,应先核对来源或询问。
上下文工程,管理的是“这一轮给什么”
本文把上下文工程理解为:为当前步骤选择、组织和更新模型需要的信息。它可能包括任务指令、相关代码、参考文档、工具说明、工具结果和阶段状态。
Prompt 的措辞属于其中一部分。外围程序把哪些文件读进来、怎样筛选搜索结果、何时整理旧对话,也会影响模型看到的任务。
你可以用三层资料来组织一个长任务:
1 | 现行任务:本次目标、边界、验收标准 |
无需每轮把三层全部展开。先提供现行任务和必要状态,再按当前问题读取资料。例如正在处理文件重名,就给冲突处理代码和对应测试;讨论命令行参数时,则看入口和项目已有约定。
这不是“越少越好”。遗漏关键约束同样会出错。目标是让每份资料都有进入本轮的理由,而不是为了显得准备充分,把整个仓库、全部日志和过时方案一次性塞进去。
OpenAI 关于维护 Agent 指令的文章也强调按任务需要读取资料,并提醒过宽、冲突的技能指导可能引入不相关信息。
给当前需求一份清楚的版本
下面仍是教学用的假设任务说明。它延续上例,不代表本文真的开发或运行了这个脚本。
1 | ## 当前任务:下载目录整理脚本 |
相应示例也要一起更新:
1 | 输入:report.PDF、photo.jpg、notes.txt |
如果正文已经改成“只处理 PDF”,示例却还把 JPG 放进 images,那么你刚整理的新上下文,又留下了一条旧指令。
因此,需求变更时应连着检查规则、示例和验收标准。只在聊天末尾加一句“以这个为准”,很容易让相关材料继续处在互相打架的状态。
不贴全部资料,给一张能找得到的地图
对文件型项目,可以准备一个短索引。下面的路径也是示意,按项目实际结构调整:
| 资料 | 什么时候读 | 怎样核对 |
|---|---|---|
| docs/task-current.md | 开始或恢复这个任务时 | 核对目标、范围和有效版本 |
| docs/decisions.md | 遇到方案冲突或想改回旧行为时 | 查看决定来源、原因和被替代状态 |
| 整理脚本的入口与相关模块 | 改参数、计划生成或移动逻辑时 | 读当前代码,不只依赖旧摘要 |
| 对应测试与运行记录 | 判断行为是否满足要求时 | 区分测试预期、实际执行结果和失败记录 |
有了索引,Agent 才有机会按问题找资料。索引写得漂亮但目标文件不存在,或者当前环境没有读取工具,仍然无法获得上下文。
同样,搜索命中也不等于内容正确。检索找到一份旧 README 时,还要检查它适用哪个版本。文档里的建议、用户的明确变更和代码的实际行为,可能需要交叉核对。
“有记忆文件”与“本轮读到了”,是两回事
把几段话写进文件,只完成了存储。运行时是否发现它、什么时候加载、模型是否引用了其中的规则,是后续几个问题。
可以把记忆粗略分成稳定约定和任务状态:代码风格、常用测试入口等适合复用;“这一轮暂时不处理照片”则应留在本次任务范围内,并标明生效条件。否则临时决定可能被带进下一个无关项目。
OpenAI 的记忆与压缩示例提供了一个有用的分工:压缩帮助当前长任务继续,记忆保存可复用的流程经验,而经过审阅的产物保留需要依赖的事实。这里借用这个设计思路,不把它说成所有平台都必须遵循的统一标准。
想检查 Agent 是否用到了现行资料,可以要求它简短列出本次依据的文档版本和关键约束,再核对读取记录与输出行为。只看到一句“我记得”,不能证明它读到了正确版本;即使读取成功,仍需验证实现是否遵守了规则。
阶段摘要要能接手工作,不能只写“已经做了很多”
长任务暂停、切换会话或进入下一阶段时,可以保存下面这样的交接记录。模板中的字段需要按实际情况填写,不是测试通过的示例报告。
1 | ## 工作交接 |
摘要里的错误会被带到后面。不要把“推测是权限问题”压成“确定是权限问题”,也不要把“生成了代码”压成“测试通过”。保留指向原始证据的入口,接手者才能在必要时重新核对。
上下文窗口有容量限制,这一点在 OpenAI 的会话状态文档中有明确说明。对话变长时,具体系统可能使用压缩或其他历史管理机制;不能假设界面还显示的所有内容都完整进入了每一次调用。
也要区分上面的可读交接摘要与平台的自动压缩。OpenAI 的Compaction 文档说明,其压缩结果可以包含不供人直接阅读的状态条目。两者都服务于后续工作,但形式和保存内容不同,不能把手写 Markdown 当成所有系统自动压缩的内部实现。
怎样判断整理真的有帮助?
拿一个有需求变更的任务,保留原始对话,再制作现行任务说明和交接记录。比较恢复任务后的输出时,重点检查:
- 有没有恢复已经废弃的默认行为;
- 规则、示例和测试预期是否一致;
- 有没有把未验证的猜测当成事实;
- 接手者能不能找到证据,并执行明确的下一步。
如果要测试模型效果,尽量固定模型、工具和任务样本,再观察上下文整理带来的变化。本文没有做这种模型对照实验,也不承诺整理后必然成功;资料组织错误、读取失败和模型判断失误都仍然可能发生。
“越聊越跑偏”并非长对话的必然结局。我们需要检查的,是新要求是否已经落到现行资料里,以及下一轮是否能拿到它们。
下次你准备发“继续刚才的任务”时,可以先整理四件事:当前目标、仍然有效的决定、已完成的证据、接下来的一步。 让接手者从一个能核对的工作状态出发,比让它重新猜一遍整段讨论更容易检查和维护。