假设你正在让 Agent 写一个整理下载目录的脚本。

第一轮,你说:“按文件类型分文件夹,直接移动就行。”第二轮,你改主意:“先给我看计划,确认后再执行。”第三轮,你又补充:“照片先别动,这次只整理 PDF。”

过了一段时间,Agent 交出了新版本。它也许记住了“整理目录”,却仍然把照片列进移动计划,甚至恢复了第一轮的默认执行方式。

你想问:刚刚不是说过了吗?

问题可能发生在理解、实现或验证任何一层。但还有一层值得检查:这一轮它实际拿到了什么资料,资料之间有没有冲突,以及谁负责把“讨论过程”整理成“当前任务”。

上一篇讲 Prompt 工程,解决怎样把需求说清楚。这篇往前走一步:需求会变化,我们怎样把正确的信息持续交给 Agent?

聊天记录是过程,当前要求需要单独站出来

长对话里,往往混着现行要求、旧方案、临时猜测、工具报错和已经修复的问题。这些信息都可能有用,却不该拥有相同的执行地位。

刚才的假设任务可以整理成这样:

讨论阶段 当时的决定 当前状态
第一轮 默认直接移动,处理 PDF 和照片 默认执行方式与照片处理范围已被后续要求替代
第二轮 默认展示计划,显式操作才执行 继续有效
第三轮 本次只处理 PDF,照片保留原位 本次任务有效

表里的“已替代”很重要。它让后续接手者知道旧方案为什么出现,也知道为什么不该再照着实现。把历史全部删除,会丢掉变更理由;把历史全部当指令,会制造冲突。

这里讨论的是同一用户对同一任务的明确变更,不能机械套成“最后出现的文字优先”。网页、代码注释、工单正文里出现的命令,并不因此成为用户的新要求。来源不同、适用范围不明时,应先核对来源或询问。

上下文工程,管理的是“这一轮给什么”

本文把上下文工程理解为:为当前步骤选择、组织和更新模型需要的信息。它可能包括任务指令、相关代码、参考文档、工具说明、工具结果和阶段状态。

Prompt 的措辞属于其中一部分。外围程序把哪些文件读进来、怎样筛选搜索结果、何时整理旧对话,也会影响模型看到的任务。

你可以用三层资料来组织一个长任务:

1
2
3
现行任务:本次目标、边界、验收标准
工作状态:已经完成什么、卡在哪里、下一步是什么
可查资料:代码、文档、历史决定和原始日志的索引

无需每轮把三层全部展开。先提供现行任务和必要状态,再按当前问题读取资料。例如正在处理文件重名,就给冲突处理代码和对应测试;讨论命令行参数时,则看入口和项目已有约定。

这不是“越少越好”。遗漏关键约束同样会出错。目标是让每份资料都有进入本轮的理由,而不是为了显得准备充分,把整个仓库、全部日志和过时方案一次性塞进去。

OpenAI 关于维护 Agent 指令的文章也强调按任务需要读取资料,并提醒过宽、冲突的技能指导可能引入不相关信息。

给当前需求一份清楚的版本

下面仍是教学用的假设任务说明。它延续上例,不代表本文真的开发或运行了这个脚本。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
## 当前任务:下载目录整理脚本

### 生效范围
本次迭代只处理指定目录第一层的 PDF 普通文件,扩展名忽略大小写。
照片、其他扩展名、子目录和符号链接均跳过。

### 当前行为
- 默认只输出计划,不创建目录、不移动文件。
- 调用者显式传入 --apply 才执行移动。
- PDF 移入 documents;目标重名时跳过,不覆盖、不删除。

### 已替代的要求
- 第一轮“默认直接移动”已被“默认预览”替代。
- 第一轮“同时整理照片”在本次迭代中已被“只整理 PDF”替代。

### 验收标准
- 预览前后目录内容不变。
- 执行后 PDF 分类正确,照片和其他跳过项目保持不变。
- 同名目标内容不变,待移动的原文件仍在原位。

### 权限边界
可以修改项目代码并在临时测试目录验证。
本次任务不授权对真实下载目录执行移动。

相应示例也要一起更新:

1
2
3
4
5
输入:report.PDF、photo.jpg、notes.txt
当前预期:
report.PDF → documents/report.PDF
photo.jpg → 跳过,本次只处理 PDF
notes.txt → 跳过,类型不在本次范围

如果正文已经改成“只处理 PDF”,示例却还把 JPG 放进 images,那么你刚整理的新上下文,又留下了一条旧指令。

因此,需求变更时应连着检查规则、示例和验收标准。只在聊天末尾加一句“以这个为准”,很容易让相关材料继续处在互相打架的状态。

不贴全部资料,给一张能找得到的地图

对文件型项目,可以准备一个短索引。下面的路径也是示意,按项目实际结构调整:

资料 什么时候读 怎样核对
docs/task-current.md 开始或恢复这个任务时 核对目标、范围和有效版本
docs/decisions.md 遇到方案冲突或想改回旧行为时 查看决定来源、原因和被替代状态
整理脚本的入口与相关模块 改参数、计划生成或移动逻辑时 读当前代码,不只依赖旧摘要
对应测试与运行记录 判断行为是否满足要求时 区分测试预期、实际执行结果和失败记录

有了索引,Agent 才有机会按问题找资料。索引写得漂亮但目标文件不存在,或者当前环境没有读取工具,仍然无法获得上下文。

同样,搜索命中也不等于内容正确。检索找到一份旧 README 时,还要检查它适用哪个版本。文档里的建议、用户的明确变更和代码的实际行为,可能需要交叉核对。

“有记忆文件”与“本轮读到了”,是两回事

把几段话写进文件,只完成了存储。运行时是否发现它、什么时候加载、模型是否引用了其中的规则,是后续几个问题。

可以把记忆粗略分成稳定约定和任务状态:代码风格、常用测试入口等适合复用;“这一轮暂时不处理照片”则应留在本次任务范围内,并标明生效条件。否则临时决定可能被带进下一个无关项目。

OpenAI 的记忆与压缩示例提供了一个有用的分工:压缩帮助当前长任务继续,记忆保存可复用的流程经验,而经过审阅的产物保留需要依赖的事实。这里借用这个设计思路,不把它说成所有平台都必须遵循的统一标准。

想检查 Agent 是否用到了现行资料,可以要求它简短列出本次依据的文档版本和关键约束,再核对读取记录与输出行为。只看到一句“我记得”,不能证明它读到了正确版本;即使读取成功,仍需验证实现是否遵守了规则。

阶段摘要要能接手工作,不能只写“已经做了很多”

长任务暂停、切换会话或进入下一阶段时,可以保存下面这样的交接记录。模板中的字段需要按实际情况填写,不是测试通过的示例报告。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
## 工作交接

### 当前目标
实现当前版本的 PDF 整理规则,默认预览,显式参数才执行。

### 已完成
填写实际修改的文件和完成的行为;没做完就明确标成进行中。

### 证据
- 现行要求:文档路径、版本或更新时间。
- 代码状态:相关文件或提交。
- 检查结果:实际执行的命令、结果、未检查的部分。
“计划测试”和“已经通过”分别记录。

### 待处理
列出尚未完成的行为、当前错误和最小复现条件。

### 决策与不确定性
记录已替代的要求,以及仍需确认的信息。

### 下一步
说明下一个可执行动作,并保留原有权限边界。

摘要里的错误会被带到后面。不要把“推测是权限问题”压成“确定是权限问题”,也不要把“生成了代码”压成“测试通过”。保留指向原始证据的入口,接手者才能在必要时重新核对。

上下文窗口有容量限制,这一点在 OpenAI 的会话状态文档中有明确说明。对话变长时,具体系统可能使用压缩或其他历史管理机制;不能假设界面还显示的所有内容都完整进入了每一次调用。

也要区分上面的可读交接摘要与平台的自动压缩。OpenAI 的Compaction 文档说明,其压缩结果可以包含不供人直接阅读的状态条目。两者都服务于后续工作,但形式和保存内容不同,不能把手写 Markdown 当成所有系统自动压缩的内部实现。

怎样判断整理真的有帮助?

拿一个有需求变更的任务,保留原始对话,再制作现行任务说明和交接记录。比较恢复任务后的输出时,重点检查:

  • 有没有恢复已经废弃的默认行为;
  • 规则、示例和测试预期是否一致;
  • 有没有把未验证的猜测当成事实;
  • 接手者能不能找到证据,并执行明确的下一步。

如果要测试模型效果,尽量固定模型、工具和任务样本,再观察上下文整理带来的变化。本文没有做这种模型对照实验,也不承诺整理后必然成功;资料组织错误、读取失败和模型判断失误都仍然可能发生。

“越聊越跑偏”并非长对话的必然结局。我们需要检查的,是新要求是否已经落到现行资料里,以及下一轮是否能拿到它们。

下次你准备发“继续刚才的任务”时,可以先整理四件事:当前目标、仍然有效的决定、已完成的证据、接下来的一步。 让接手者从一个能核对的工作状态出发,比让它重新猜一遍整段讨论更容易检查和维护。

上一篇:Prompt 工程:怎样把需求写成 Agent 能完成的任务?