上下文管理:让它看见该看的,而不是全部

一个任务效果差,八成不是模型不行,而是它看到的东西不对:贴了 800 行文件,其实只用一个类型定义;真正该读的三个调用方没给;反倒把锁文件、生成代码、三个月前的报错日志一起塞了进去。代码场景的上下文素材是可检索的仓库,所以核心动作就三步:先定位、再给料、用完就清。

三层上下文:常驻、按需、临时

层次载体放什么容量控制
常驻AGENTS.md、README、docs/agents/codemap.md命令入口、目录职责、约定与边界越短越稳,控制在百行内
按需具体文件、类型定义、调用方、测试、接口文档本次任务真正相关的代码用检索与 @file 精确取,不整仓灌入
临时报错日志、git diff、本次任务描述当次排错所需的最小现场用完即弃,别留成历史包袱

分清这三层,大部分「效果不稳定」问题就有了答案:要么常驻层没写好(每次都要重讲规矩),要么临时层没清干净(旧错误被当成新事实)。

别贴代码,给检索指令

它自己检索回来的上下文比你手工挑的更准,也更省事——前提是把检索步骤写清楚。

先不要改代码。按下面顺序检索并汇报:
1) 用 grep 找出 UpdateOrderStatus 的所有定义与调用点,列出「文件:行号」;
2) 打开调用点最多的 3 个文件,说明调用链与各自的责任;
3) 列出相关测试文件,以及它们覆盖了哪些场景、漏了哪些;
4) 汇报你读了哪些文件、哪些没读、还缺什么信息。
我确认后你再动手改。

第 4 条是关键:让它交代读了什么,你才能判断它的结论有没有建立在错误或缺失的上下文上。

给任务配一个「上下文包」

比零散交代更好用的是把上下文写成一份短文件,随任务一起给它。六项即可,缺哪项就在那一项写「待确认」:

## 任务:给 GET /orders 增加分页
- 验收:`go test ./internal/order/... -run TestListOrders -count=1 && make check`
- 涉及:`internal/order/handler.go`、`service.go`、`repo.go`
- 参照:`internal/user/handler.go` 的 ListUsers(照抄它的分页风格与参数名)
- 约束:不改表结构;不引入新依赖;现有响应字段与顺序保持不变
- 样例:见 `testdata/orders_page.json`
- 未知:前端是否依赖返回数组长度?——先确认,再动手

这份东西同时解决三件事:范围清楚、风格有参照、未知项被显式提出。它还可以直接落盘成 docs/agents/task-orders-page.md,下次开新会话接着用。

大仓库怎么给上下文

仓库大到无法整体读完时,先给「地图」,再给「街区」:

# 先确认仓库边界与规模(这些数字本身就是重要上下文)
git rev-parse --show-toplevel
go list ./... | head -30                     # Go:包清单
find apps -maxdepth 2 -type d | head -20     # monorepo:应用边界
rg --files-with-matches 'type Order struct'  # 关键类型的落点
rg -c 'UpdateOrderStatus' --glob '!vendor/**' | sort -t: -k2 -nr | head

再配一份人工维护的、只有二三十行的代码地图 docs/agents/codemap.md:

# 代码地图
- 订单主链路:handler → service → repo,入口 `internal/order/handler.go`
- 幂等:Redis 键 `order:idem:<key>`,实现见 `internal/platform/idempotency`
- 金额单位:全链路统一用「分」,出入参转换只在 handler 层做
- 异步任务:`internal/worker/`,任务定义集中在 `task.go`

这是投入产出比最高的一份上下文:人维护它只需半小时,却能让 AI 少走一半弯路。

上下文预算:三类内容不值得给

内容为什么不该给换成什么
锁文件、dist/、vendor/、*.min.js、快照体积大、信息密度低,挤掉真正相关的代码写进工具的排除配置
整个文件只为看一个类型无关代码稀释注意力只贴该类型,或让它自己 grep
历史对话里的旧结论可能已被推翻,却被当成前提只保留最新结论,开新会话
{
  "excludeGlobs": [
    "**/vendor/**", "**/dist/**", "**/*.lock", "**/*.min.js",
    "**/__snapshots__/**", "**/testdata/fixtures/large/**"
  ]
}

会话管理:一个任务一个会话,结论落到文件

上下文里最贵的不是代码,而是已经过期却还在被引用的对话历史。两条纪律:

  • 换任务就开新会话,把上一段结论写成文件带走,而不是靠聊天记录回忆。
  • 阶段性成果落盘,让下一次会话有干净的起点:
请把当前进展写到 docs/agents/task-orders-page.md,包含四节:
已完成(含改动文件清单)、当前状态(make check 的结果)、未决问题、下一步命令。
写完就停,不要继续改代码。

下一次只要说「读 docs/agents/task-orders-page.md,继续未决问题」,就省掉了重新交代背景的成本。

常见坑

坑后果规避
一次粘贴十个文件关键信息被稀释,答案泛化先给检索指令,只喂相关片段
只给文件不给验收方式它不知道「读到哪里算够」上下文包里写清验收命令
让它在无关代码里找答案编造调用方与工具函数指明关键类型的落点,或用 grep 定位
生成代码、锁文件进了上下文白占预算还引入噪音配排除规则
一个会话从需求聊到上线旧结论被反复当成前提按任务切会话,结论落盘
代码地图只在某人脑子里人和 AI 都要重新摸索落成二三十行的 docs/agents/codemap.md

小结:上下文管理的目标不是「给得多」,而是常驻层薄而稳、按需层用检索精确取、临时层用完就清;别贴代码,写检索指令并让它汇报读了什么;每个任务配一份六项上下文包,阶段性结论落成文件而不是留在对话里——你给它的现场越准,它需要猜的东西就越少。

笔记加载中…