AI Agent 的"上下文窗口"开始不够用了,我换了三种方法才把它的注意力稳住

我有个项目,最早用 Cursor 写的时候,五六个文件随便让它跑。现在这个项目迭代了大半年,主分支上几百个文件,三个微服务共享同一份数据库 migration,最近一次让 Claude Code 帮我改一个支付回调的字段,AI 直接给我生成了一个看起来对、跑起来也能编译、但放到生产环境会扣错钱的版本。

排查的时候我去翻它的推理过程,发现它在第 23 步就把”这个字段是 string 类型”这事儿给忘了。后面 14 步全在围绕一个错的假设展开,最后输出一个逻辑自洽的 bug。

这件事让我意识到一个问题:“上下文窗口 100 万 token”和”AI 真的读进去了 100 万 token”,根本不是一回事

我以前以为,模型能塞下 100 万 token 的文件内容,那就等于我整个项目都”在它的脑子里”。实际操作下来才发现,AI 的注意力是有瓶颈的,给它越多材料,它反而越容易分心。

后来我花了大概一个多礼拜,把项目的工作流重新理了一遍。我不是模型研究者,下面的方法都是从代码里一次次试出来的,没有学术严格性,但管用。


先解释清楚我在说什么

如果你是用 AI 写代码比较早的那批用户,应该会有类似的体感:项目小的时候,Cursor Composer、Copilot Chat、Claude Code 怎么玩都顺手。但项目复杂度上来之后,AI 突然变得”笨了”——同一个需求,三周前它能一次写对,现在改三遍都不行。

这件事有个学术名字,叫 Lost in the Middle。大意是:模型对输入的开头和结尾记得最清楚,中间部分容易”看走眼”。原始论文(Stanford 和 Samaya AI 2023 年的研究)测出来,对于一段 2000 token 的输入,开头和结尾位置的信息召回率能到 70% 以上,正中间的位置掉到 40% 多。

100 万 token 的窗口里,这个效应不是消失了,是被放大了。因为材料越多,”中间”越长,越容易丢东西。

我自己的体感是:当我给 Agent 喂超过 30-40 个相关文件,它开始犯低级错(忘字段、混变量、引用不存在的文件)的概率会显著上升。40-100 个文件,它开始产出”看起来对但其实跑不通”的代码。100 个文件以上——基本就在赌运气。

这件事不是”模型不够聪明”造成的,是注意力分配的物理限制。所以解决思路也不是”换个更强的模型”,而是主动管理它看什么、看多少、按什么顺序看


方法一:把项目”目录化”喂给 AI

我最早的做法是让 AI 自己 @ 文件或者 find 整个项目。后来发现这等于让一个注意力分散的人去图书馆自己找资料——它会去,但找回来的东西经常跑偏。

现在的做法是,每个项目我都维护一个 AGENTS.md(这个文件名很多 Agent 工具会优先读),里面不长,大概是这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# Project Map

## 核心服务
- `services/payment/` - 支付网关,端口 8000,对外暴露 gRPC
- `services/order/` - 订单服务,端口 8001
- `services/user/` - 用户服务,端口 8002

## 数据库
- 单一 Postgres 实例,schema 见 `db/migrations/`
- 所有服务共享同一个 migration 目录
- 字段命名 snake_case,不允许 camelCase

## 关键约束
- 支付回调必须 idempotent,重试逻辑在 `payment/callback.go`
- 订单状态变更需要走事件总线(`events/order_events.go`)
- 所有金额用 int64 存(分),不允许 float

## 不允许动的目录
- `legacy/` - 老系统的桩文件,不允许修改,但可以引用
- `vendor/` - 第三方依赖

这个文件有什么作用?让 AI 在做任何事之前,先读到一份”项目地图”。它接下来去找文件、改代码的时候,会基于这份地图判断”我应该动哪里、不应该动哪里”。比让它自己摸索高效得多。


方法二:分阶段拆任务,而不是一次塞完整需求

第二种方法,是任务设计上的改变。

我以前写给 Cursor 的 prompt 大概是这样的:

帮我把支付回调改成支持支付宝退款回调。

这种 prompt 看上去很明确,实际上信息量很少。AI 拿到这个任务会去做什么?它会把所有 payment/ 目录下的文件全读一遍,然后试图一次性给你一个完整的方案。

现在的写法是这样的:

任务 1:先读 payment/callback.gopayment/types.go,告诉我现有的回调处理函数是怎么实现的,有哪些事件类型、哪些状态字段。

看完之后,告诉我你打算怎么改,再开始动手。

这一步等 AI 跑完,我自己看一眼它的理解对不对,再让它开始写。

第二个 prompt 是:

任务 2:基于你刚才的总结,修改 payment/alipay_callback.go,新增一个退款回调处理函数。要求:

  • 复用现有的 idempotent 中间件
  • 退款金额校验逻辑写在 payment/validation/refund.go
  • 不要改 payment/types.go(如果需要改,告诉我为什么)

改完先跑测试 go test ./payment/...,把测试结果给我看。

第三步:

任务 3:如果测试都过了,再读一遍你改的代码,写一个总结给我,列出你做了哪些改动、为什么、改了哪些文件之外的东西。

这种”分阶段”的方法,本质上是把一个大的上下文拆成 N 个小上下文。每个小任务里,AI 只需要关注”当前这一步”相关的文件,注意力就不会被稀释。

我后来用 GitHub CopilotClaude Code 都有类似的体感:让 AI 一次只做一件事,比一次让它做一整套事情靠谱得多。


方法三:把”重点提示”放在文件开头和结尾

第三个方法,是我从 Lost in the Middle 那篇论文里直接抄来的。

既然模型对开头和结尾记得最清楚,那我就在它要读的文件前面和后面各塞一段”重点提醒”。

具体怎么做的?用一个 .cursor/rules 或者 CLAUDE.md 之类的规则文件,针对特定目录加规则。比如我的 services/payment/ 目录有个规则文件是这样的:

1
2
3
4
5
6
7
8
9
10
11
12
# 服务规则:支付 (payment)

## 必读(读这部分代码之前先看)
- 本服务所有金额字段都是 int64(分),不是 float
- 所有外部回调必须走 idempotent 中间件
- 数据库 schema 见 db/migrations/0042_payment_*.up.sql
- 涉及 schema 变更不允许私自改,必须先报告

## 重要约束(写完代码再看一遍)
- 重试逻辑必须有上限,最多 3 次
- 所有回调函数必须返回 error,不允许 panic
- 退款必须先校验原订单状态,不允许直接修改

第一段”必读”放在 AI 即将打开相关文件时最先看到的位置,第二段”重要约束”放在它写完代码、准备让我看的位置。

这样做的原理很简单:让 AI 在”开始工作”和”结束工作”这两个最容易记住的时刻,都看到最重要的约束。中间那段”它实际写代码的过程”,哪怕它真的注意力分散了,开头结尾两边的强化也能把关键信息顶住。

Claude Code 这边有个官方支持的 hooks 机制可以更精细地控制——比如在 AI 读完 payment/callback.go 之后,自动注入一段”金额校验”的提醒。我目前在测这个组合,但还没完全稳定,先不放出来。


这些方法不能解决什么

老实说,这三个方法都是”减缓症状”,不是”根治问题”。

根上的问题是:上下文窗口大了,注意力分配能力没跟上。AI 仍然会丢关键约束,会在长会话里自打嘴巴。

下面这些情况,这三个方法帮不上太多:

  • 跨服务的事务一致性。比如”用户下单后通知库存系统 + 支付系统 + 物流系统”。三个服务分布在不同目录里,AI 还是容易搞混调用顺序。
  • 跨 PR 的代码风格统一。如果两个 PR 由 AI 各自生成,它们很容易生成风格不一的代码(比如一个用 zap log,一个用 logrus)。
  • 测试覆盖率。我试过让 AI 给一个 2000 行的服务补单元测试,它给我生成了 60% 行覆盖率,但关键的边界条件(空指针、nil slice、超时)一个都没覆盖。

这些事目前还是得靠人盯。AI 是个强辅助,不是替代品。


我现在的默认工作流

总结一下,我现在每天写代码的工作流是这样的:

  1. 进入项目第一件事:确认 AGENTS.md 是最新的(同事改了什么新约束我会同步进去)
  2. 任何任务开始之前:先把任务拆成 2-4 个小任务,每个步骤明确”读什么、改什么、跑什么测试”
  3. 每个步骤结束之后:让 AI 自己总结一下它做了哪些改动,我扫一眼 diff
  4. 关键代码改完之后:单独让 AI 读一遍相关文件,列出它看到的”重点约束”,看它有没有漏

这套流程不能让我跑得更快。但能让我少掉几次坑。尤其是那种”AI 改完之后没冒烟测试、直接合到主分支、线上出了事”的坑。

上次那个支付回调的 bug,按这套流程走了一遍,AI 还是在第三步的时候把字段类型搞混了——但因为我让它在任务 3 里”自己列一遍字段定义”,我自己看了一眼,发现它把 amount_int64 写成了 amount,提了一句让它改了。

如果当时我让它一次性写完,我可能也得排查半天才能发现这个 bug。

工具越来越强,但人的注意力还是比 AI 的注意力贵一点。这件事我觉得接下来几年都不会变。


AI Agent 的"上下文窗口"开始不够用了,我换了三种方法才把它的注意力稳住
https://www.ohtudou.top/2026/09/07/2026-09-07-ai-agent-context-window-management/
作者
Tudo
发布于
2026年9月7日
许可协议