迭代检索:让 Agent 自己找到它需要的上下文
派发子 Agent 处理代码库任务时,我最初的直觉是「把相关文件一起喂进去」。问题是,相关文件是什么,我自己也不总是清楚——更何况 Agent。结果要么上下文太大超出限制,要么漏掉关键文件导致输出跑偏。
这是一个比 token 预算更根本的问题:子 Agent 在开始工作之前,本就不知道自己需要什么上下文。
问题的三种错误解法
处理这个问题有三种直觉反应,每种都有明显缺陷:
- 全量发送:把整个代码库或所有可能相关的文件都喂进去。超出上下文限制是小事,更大的问题是 Agent 在噪音里迷失方向,输出质量反而下降。
- 不发任何上下文:让 Agent 自己去探索。听起来优雅,但 Agent 对陌生代码库几乎毫无概念,探索方向往往是错的。
- 凭感觉猜:人工判断「大概需要这几个文件」,一次性发出去。命中率不稳定,而且对不熟悉的模块尤其不可靠。
三种方法的共同缺陷是:它们都是一次性决策,没有利用执行过程中发现的信息来修正自己。
迭代检索的四步循环
迭代检索的核心思路是:把「找上下文」本身做成一个可以自我修正的循环,而不是一次性猜测。
第一步,宽泛派发(DISPATCH)
用任务意图构建初始查询——关键词宽泛,范围大,目的不是精准命中,而是把候选文件捞出来。这一步宁可多捞,不要漏。
第二步,评估相关性(EVALUATE)
对候选文件打分(0-1),分四档:直接实现目标功能的打高分,包含相关模式或类型的打中分,仅有间接关联的打低分,明确无关的直接排除。更重要的是:标记出「已知缺口」——当前上下文里还缺什么?
第三步,细化查询(REFINE)
根据评估结果更新搜索策略。高分文件里通常会暴露出项目真实使用的命名约定——比如你搜「rate limit」,代码库里实际用的词是「throttle」。把这些新词加入关键词列表,把确认无关的路径排除掉,同时把已知缺口作为新的检索焦点。
第四步,循环(LOOP)
带着精化后的查询重新检索,最多循环三次。如果已经有三个以上高相关性文件且没有明显缺口,提前结束。
最多三轮循环不是随意定的——第一轮发现命名约定,第二轮精准捞出核心文件,第三轮补全边界依赖,三轮之后收益递减。更重要的是:强制上限防止检索本身消耗掉所有 token 预算,还没开始做正事就超出限制。
为什么「发现命名约定」是关键
实践中,第一轮检索最有价值的输出往往不是文件本身,而是代码库的命名习惯。
不同项目对同一个概念的叫法千差万别:鉴权相关的文件可能叫 auth、session、identity、credential;限流可能是 rate-limit、throttle、quota;消息队列可能是 queue、job、task、event。
如果用通用词检索,第一轮大概率找不到精确命中,但能看到「高分文件用了什么词」。把这些词提取出来,第二轮的命中率会显著提高。这是迭代检索比一次性检索最大的优势所在。
落地到 Agent prompt 里
这套逻辑可以直接写进派发给检索型 Agent 的 prompt:
检索上下文时,按如下步骤操作:
1. 先用宽泛关键词搜索候选文件
2. 对每个文件评估相关性(0-1),标记当前缺少什么
3. 根据高分文件里发现的命名约定更新关键词,排除无关路径
4. 重复,最多 3 轮
5. 返回相关性 ≥ 0.7 的文件不需要复杂的框架,一段说明就够。
一句话心法
上下文不是一开始就知道的,而是通过检索→评估→精化的循环逐渐收敛出来的。