Imagine you're taking an open book exam: you technically have all the answers, but somehow that makes it even harder to find the right one. Where do you even start searching? When do you know that your sources are correct? How do you optimize your time so that you don't blow all your energy on redundant searches? Finding the right information efficiently isn't that straightforward.
想象你在考一场开卷考试:理论上所有答案都在手上,但这反而让找到对的那个更难。从哪儿开始搜?怎么确定来源是对的?怎么分配时间才不会把精力全耗在重复搜索上?高效找到正确的信息,没那么简单。
Hand an agent a question and it's left with a similar predicament: it has a limited context window, so like us humans, it has to retrieve information to complete certain tasks (instead of having everything memorized). When searching, agents struggle with: Inefficient searching — every search costs tokens and time. An agent that searches clumsily (e.g. opens every file just to see what's inside, or keeps rewording the same query) can fill its context with search results before it finds anything useful. Too much context at once — one search that dumps a full data export or a dozen documents fills the context window in a single move, leaving no room for the work itself. Irrelevant or stale context — outdated or off-topic information can look just as convincing to a model as the right answer. Once it's in the context window, the agent may build on it (and the mistake will carry through every step after).
把问题交给 agent,它面临同样的困境:上下文窗口有限,像人类一样得靠检索(而不是全记住)来完成任务。搜索时 agent 会卡在三种失效上:**低效搜索**——每搜一次都花 token 与时间,笨拙的搜索(比如为看内容而打开每个文件、或反复换措辞重搜同一条)可能在找到有用信息之前就把上下文塞满;**一次太多**——一次搜索倒进整份数据导出或一打文档,一步就把窗口填满,干活的地方都没了;**无关或过期**——过时或跑题的信息对模型来说看起来与正确答案一样有说服力,一旦进了上下文窗口,agent 可能在它上面继续搭建(错误会传导到之后的每一步)。
Luckily, there are several techniques at an agent's disposal that allow it to retrieve the correct information. It's the job of an agent harness to apply these techniques strategically to get the model the right context at the right time for the given task. This blog covers the challenges with agent retrieval (finding and pulling in only the information necessary for the task at hand), the techniques at our disposal to combat them, and how to keep these in mind when designing an agent harness (using LangChain's Deep Agents harness as an example). For more on how to manage context once it's in the context window, check out this blog on Context Engineering.
幸运的是,agent 手上有一批技术可以让它取回正确的信息。Agent harness 的职责就是战略性地应用这些技术,让模型在给定任务的正确时机拿到正确的上下文。本文覆盖 agent 检索的挑战(找到并只拉进当前任务必需的信息)、应对技术与设计 harness 时的注意点(以 LangChain 的 Deep Agents 为例)。信息进入上下文窗口之后怎么管理,见另一篇 Context Engineering 博客。
Our example: a competitive analysis agent · 示例:竞品分析 agent
Let's see how this can be applied in a real-world use case: a competitive analysis agent. Every Monday, an agent researches hundreds of competitors and writes a report in the team's template. It needs to: find last week's notes on Company A; look up a specific revenue number in a huge market data export; search a news archive for anything new. Each of these is a different kind of retrieval and therefore faces different problems.
看看真实用例:一个竞品分析 agent。每周一调研数百家竞品、按团队模板写报告。它要:找 A 公司上周的笔记;在巨大的市场数据导出里查某个营收数字;搜新闻档案找新动向。每一项都是不同种类的检索,面对的问题也不同。
1. Inefficient searching · 一、低效搜索
Our agent has to find three things for each competitor. If each one takes a dozen tries (opening files just to see what's inside, or rewording a search because the source uses different words), its context window fills up with failed searches before it even writes a word of the report. Therefore, the best search is the one the agent doesn't have to repeat, and that means using the right tool for each job.
我们的 agent 每家竞品要找三样东西。如果每样都要试十几次(开文件只为看看里面有啥,或因为来源用词不同而反复改写搜索),那报告还没写一个字,上下文窗口已经被失败搜索填满了。所以,最好的搜索是不必重来的搜索——每件活用对工具。
### Start with the built-in filesystem tools · 先用内置文件系统工具 One of the most common ways for an agent to search through information is with a filesystem. However, if our agent opens every file to see what's inside, it's searching very inefficiently: each file it reads lands in its context window, so it can fill up just from looking. A better approach is to check names and keywords first (the way you'd scan a book's index instead of reading every page during an open-book exam). Two common filesystem tools do exactly that: glob finds files by name pattern. For example, **/company-a*.md finds last week's notes on Company A. grep searches inside files without loading them into the context window. It matches literal text and can return the matching files, the matching lines, or counts.
agent 搜信息最常见的方式之一是文件系统。但如果它打开每个文件看内容,搜索效率极低:读过的每个文件都落进上下文窗口,光「看」就能把窗口看满。更好的做法是先查名字与关键词(就像开卷考试先扫书后的索引,而不是逐页读)。两个常见文件系统工具正是干这个的:**glob** 按文件名模式找文件——比如 `**/company-a*.md` 定位 A 公司上周的笔记;**grep** 在不装载文件进上下文的前提下搜内容——匹配字面文本,可返回匹配的文件、匹配行或计数。
Every deep agent comes with these tools built in, alongside ls, read_file, write_file and edit_file. The same tools work no matter where the files live (agent state, local disk, a persistent store or a sandbox), because they all go through the agent's backend.
每个 deep agent 都内置这些工具,连同 ls、read_file、write_file 与 edit_file。无论文件住在哪里(agent 状态、本地磁盘、持久存储或沙箱),同一套工具都照常工作——因为都经过 agent 的 backend。
### Add a retrieval tool when keywords aren't enough · 关键词不够时加检索工具 Grep is great when you know what words to look for, but it only matches the exact text you give it. That's a problem for the third job in our example: searching a news archive for anything new. If our agent greps for "Company A funding," it will miss an article titled "Company A closes $50M Series B," even though that's exactly what it's looking for.
知道要找什么词时 grep 很棒,但它只匹配你给它的精确文本。示例的第三项任务(搜新闻档案找新动向)就栽在这:agent grep「Company A funding」,会漏掉标题为《Company A closes $50M Series B》的文章——尽管那正是它要找的。
To search by meaning instead of exact words (semantic search), you add a retrieval tool backed by a vector store. A retrieval tool is any tool the agent can call to fetch information: it takes a query, looks it up in some data source, and returns what it finds (the closest matches). How a retrieval tool matches depends on the data source behind it. Backed by a vector store, it matches by meaning, but a retrieval tool can sit on top of other data sources too: a SQL database, for structured lookups (like sales figures or customer records); a search API (for fresh information from the web); an MCP server (for tools someone else already built, like a documentation search).
要按意义而非精确词搜索(语义搜索),就加一个向量库支撑的检索工具。检索工具是 agent 可调用以取信息的任何工具:接收查询、在某个数据源里查、返回找到的(最接近的匹配)。匹配方式取决于背后的数据源:向量库按意义匹配,但检索工具也可以架在别的数据源上——SQL 数据库(结构化查询,如销售数字或客户记录)、搜索 API(网上新鲜信息)、MCP server(别人造好的工具,如文档搜索)。
### Letting the agent decide when to search · 让 agent 自己决定何时搜 Many retrieval setups search once at the start, then answer. That works for an FAQ bot (2-step RAG), but not for our agent. Let's say halfway through researching Company C, it finds an article about a product launch it didn't know about, and now it needs that product's pricing (which it couldn't have known to look for at the start). With only one search, the report goes out without it. Research agents need agentic retrieval (instead of 2-step RAG): the agent decides when to search, what to search for, and whether it needs more. With Deep Agents, it already works this way by default: the agent runs in a loop and can call any tool as many times as it needs.
很多检索方案是开头搜一次然后作答。FAQ 机器人(2 步 RAG)这样没问题,我们的 agent 不行:调研 C 公司到一半,读到一篇它不知道的产品的发布报道,现在需要那个产品的定价——这是开局不可能预见到要查的。只搜一次,报告就漏着它发出去了。研究型 agent 需要的是 agentic retrieval(而非 2 步 RAG):agent 自己决定何时搜、搜什么、要不要再搜。Deep Agents 默认就是这样——agent 跑在循环里,任何工具需要调多少次就调多少次。
### Package your search know-how as a skill · 把搜索诀窍打包成技能 To help the agent search well, you can package your search know-how as a skill: a set of instructions for a specific task (like which index to use, how to phrase queries and how to format citations). The agent only sees each skill's name and a short description until a task calls for it; then it loads the full instructions, so niche know-how is there when it's needed without taking up context the rest of the time (a technique called progressive disclosure).
要帮 agent 搜得好,可以把搜索诀窍打包成 skill:针对特定任务的一组说明(用哪个索引、查询怎么措辞、引文怎么排版)。任务用到之前,agent 只看到每个 skill 的名字与一句简短描述;用到时才加载完整说明——冷门诀窍需要时就在,其余时候不占上下文(这套技术叫渐进披露,progressive disclosure)。
2. Too much context at once · 二、一次太多
However, despite optimizing the search process, even the right search can return too much. Our agent needs just one number from the market data export (Company B's quarterly revenue), but loading all 40,000 rows to find it would fill its context window. Our retrieval tool has the same problem: if it returns every news article straight to the model, four results per search across five companies adds up fast.
就算搜索过程优化好了,对的搜索也可能返回太多。我们的 agent 只需要市场数据导出里的一个数字(B 公司季度营收),但为找它装载全部 40,000 行会把上下文窗口(context window)填满。检索工具同样:若把每篇新闻文章直接返给模型,每次搜索四条、五家公司一乘,很快就爆。
### Reading large files one page at a time · 大文件一次读一页 The filesystem tools are built to return as little as possible. read_file reads a file one page at a time (100 lines by default), and the agent can set an offset (which line to start from) and a limit (how many lines to read) to jump to the part it needs. So to find Company B's revenue, the agent greps for it, then reads just the few lines around the match.
文件系统工具就为「尽量少返回」而造:read_file 一次读一页(默认 100 行),agent 可设 offset(从第几行开始)与 limit(读几行)直达需要的部分。找 B 公司营收,agent 先 grep 定位,再只读匹配处附近几行。
### Let the harness offload oversized results · 让 harness 卸载超大结果 Sometimes a tool returns more than expected anyway. When a tool result is too large (over about 20,000 tokens), the harness saves it to a file under /large_tool_results/ and gives the agent the path plus a short preview (the first and last few lines). The agent can then read back just the parts it needs with read_file's offset and limit.
有时工具还是会返回超出预期的量。结果太大(约超 20,000 token)时,harness 把它存到 /large_tool_results/ 下的文件,给 agent 路径加一段短预览(首尾几行)。之后 agent 用 read_file 的 offset/limit 只读回需要的部分。
### Have your retrieval tool return file paths · 让检索工具返回文件路径 You can apply the same idea to your own retrieval tool instead of waiting for the size limit: have it write each result to a file and return only the paths. This is the first part of a pattern called "retrieve, offload, delegate" (LangChain's RAG guide walks through it in full). Here's a simplified retrieval tool: backend = StateBackend(); @tool def search_news(query): docs = vector_store.similarity_search(query, k=4); files = [(f"/retrieved/result_{i}.md", doc.page_content) for i, doc in enumerate(docs)]; backend.upload_files(files); return "Saved results to: " + paths. Now the main agent sees four short paths instead of four full articles.
不必等大小上限,自己的检索工具也可以直接套用同一思路:把每条结果写进文件、只返回路径。这是「**retrieve, offload, delegate**」模式的第一段(LangChain 的 RAG 指南有完整走法)。简化版检索工具:search_news(query) 里 vector_store.similarity_search 取 k=4 条,backend.upload_files 把每条写进 /retrieved/result_{i}.md,返回「结果已存到:路径列表」——主 agent 看到的是四条短路径,而不是四篇完整文章。
3. Irrelevant or stale context · 三、无关或过期
Small results don't help if they're the wrong results. Any of those four files could be about a different company with a similar name, or a story from two years ago. Off-topic or outdated text looks just as convincing to a model as the right answer, so the goal is to keep it out of the main agent's context entirely.
结果小但如果结果是错的,还是没用。那四个文件任何一个都可能写的是名字相似的另一家公司,或者是两年前的旧闻。跑题或过时的文本对模型看起来与正确答案同样有说服力——目标是把它们整个挡在主 agent 的上下文之外。
### Let subagents filter the results · 让子代理过滤结果 However, the main agent still has to read those files to find out which ones matter (and every off-topic article it opens does land in its context). That's where the "delegate" part of the "retrieve, offload, delegate" pattern comes in: a subagent reads each retrieved file and returns only the key facts. Define the subagent: chunk_analyst = { "name": "chunk-analyst", "description": "Analyze one retrieved file. Pass the question and a single path under /retrieved/.", "system_prompt": "Use read_file to read the assigned file. Return the key facts and the source URL." }. Give the main agent the retrieval tool and the subagent, passing the same backend (so the subagent can read the files the tool saved). Now the flow is: Search — the main agent calls search_news and gets back four paths. Delegate — it sends each path to a chunk-analyst subagent, and they can run in parallel. Synthesize — each analyst returns a short summary with its source; the main agent combines them and searches again if something is missing.
但主 agent 还是要读那些文件才知道哪些要紧(它打开的每篇跑题文章照样落进它的上下文)——这就是「retrieve, offload, delegate」里 **delegate** 登场的地方:一个子代理读每份检索文件、只返回关键事实。定义子代理:chunk_analyst(描述=分析一个检索文件,传入问题与 /retrieved/ 下单个路径;system prompt=用 read_file 读指定文件,返回关键事实与来源 URL)。把检索工具与子代理都交给主 agent,传同一个 backend(子代理才能读工具存的文件)。流程变成:**搜索**——主 agent 调 search_news 拿回四个路径;**委托**——把每个路径发给一个 chunk-analyst 子代理(可并行);**综合**——每个分析员返回带来源的短摘要,主 agent 汇总,缺什么再搜。
Raw results go to files, the noisy reading happens in subagents with their own context windows, and the main agent only ever sees conclusions. Anything off-topic stays in the subagent's context, and the main agent's context window stays clear!
原始结果进文件,吵闹的阅读发生在各有自己上下文窗口的子代理里,主 agent 永远只看到结论。跑题内容留在子代理的上下文里,主窗口保持干净!
### Pull from up-to-date sources · 从新鲜来源取数 Filtering does keep off-topic results out, but it can't fix results that are out of date. Our competitive analysis agent runs every Monday, so last month's index won't catch this week's news. A solution: a search API or MCP server could give the agent current information (instead of whatever was indexed months ago). If your data has dates, filtering by date in the retrieval tool would also keep old results out.
过滤挡得住跑题,挡不住过期。我们的竞品分析 agent 每周一跑,上个月建的索引抓不到这周的新闻。解法:搜索 API 或 MCP server 给 agent 现时信息(而不是几个月前索引的存货);数据若带日期,在检索工具里按日期过滤也能挡掉旧结果。
### Be careful with retrieved text · 对检索文本保持警惕 On the flip side, relevant current results can cause problems! Since retrieved text is data, not instructions, anything you retrieve could contain a prompt injection (and no prompt or delimiter strategy fully prevents this). Make sure to validate outputs: check that answers cite the sources you expect and that claims match them.
反过来,相关又新鲜的结果也会出问题!检索文本是数据不是指令,你检索到的任何东西都可能藏着提示注入(而任何提示词或分隔符策略都不能完全防住它)。务必验证输出:检查答案引用的是你预期的来源、断言与来源对得上。
Retrieval strategies to keep in mind · 值得记住的检索策略
Here's what to look out for (regardless of whatever harness you're building on): Use the most efficient tool that works — if you know the words, grep beats an embedding lookup; save semantic search for when you actually need it. Page instead of loading — read large files in pieces instead of all at once. Return pointers instead of payloads — write retrieved content to files and hand the agent the paths. Delegate the reading — let subagents read and summarize so the main agent only sees conclusions. Verify grounding — check answers against what was retrieved, and treat retrieved text as untrusted.
无论基于哪个 harness,几条原则值得记:**用能奏效的最高效工具**——知道关键词时 grep 胜过嵌入检索,语义搜索留给真需要的时候;**分页而非整装**——大文件分块读,别一次全载;**返回指针而非载荷**——检索内容写文件、给 agent 路径;**委托阅读**——让子代理读并总结,主 agent 只见结论;**验证接地**——答案对照检索内容核查,把检索文本当不可信输入。
Try it · 试一试
uv add deepagents. Want to learn more from a live instructor? I'll be covering this on November 9th: Register HERE! Retrieval is only half of the story: how information finds its way to the agent. How do we manage the agent's context window as it starts to build up information over time? To learn more check out: the blog on context engineering with Deep Agents, and the Deep Agents course on LangChain Academy (free, online and self-paced).
uv add deepagents 即装。想跟直播讲师学?11 月 9 日我会讲这个主题(原文有注册链接)。检索只是故事的一半——信息怎么到达 agent;随着信息随时间累积,怎么管理 agent 的上下文窗口?延伸阅读:Deep Agents 的上下文工程博文(即本系列上篇),以及 LangChain Academy 的 Deep Agents 免费自步课程。