代理最重要的工具之一是用于构建自身上下文的搜索工具。最近,LlamaIndex 和 LangChain 的帖子引发了一场讨论:对于上下文工程来说,shell 工具和文件系统是否足够? 不幸的是,这场讨论很快偏离了主题,变成了文件系统与数据库的比较。
本文重新聚焦于问题:代理需要什么样的搜索接口来构建自己的上下文? 我们将先讨论 shell 工具与专用数据库工具之间的权衡,然后提供一个实用的框架,帮助你为代理的需求找到合适的接口。
在早期的检索增强生成(RAG)管道中,开发者设计了固定的检索流程,而大语言模型(LLM)只是上下文的被动接收者。这是一个根本的限制:无论是否需要,上下文在每次查询中都被检索,而没有检查它是否真的有帮助。
随着代理型 RAG 的转变,代理现在可以访问一组搜索工具来构建自己的上下文。例如,Claude Code [1] 和 Cursor [2] 允许代理根据任务的实际需要,在不同的搜索工具之间选择,甚至将它们组合起来进行链式查询。
上下文可以存在于不同的位置,例如网络、本地文件系统或数据库。代理可以通过不同的工具与这些外部数据源进行交互:
run_esql(query) 或 db_list_index()),可以用于查询数据库。
图解展示了代理如何使用不同的上下文检索工具访问本地文件、专有数据、网络和长期记忆。
如图所示,shell 工具用途广泛,可以用于从不同的数据源中检索上下文,包括:
elasticsearch-sql-cli),通过 curl 调用 HTTP API,或运行脚本,这在与代理技能结合时尤为有用,后者是注入代理上下文的可重用、记录示例,引导工具的正确使用(例如,Elastic Agent Skills for Elasticsearch)。然而,shell 工具提供了直接的系统访问,因此需要安全措施,如在隔离的沙箱环境中运行并记录所有执行的命令。
合适的搜索接口取决于你的数据、查询模式和用例。本节提供了一个实用的起点。
文件系统与数据库的讨论并不是关于存储层。例如,LangChain 解释说,他们的记忆系统实际上并没有在真实的文件系统中存储记忆,而是将记忆存储在数据库中,并将其_表示_为一组文件给代理 [3]。
文件系统自然适合文件原生的用例,如编码代理。它们也很适合作为临时的草稿或工作记忆,适用于并发性不是问题的单用户或单代理场景。在这些情况下,物理文件系统或将数据表示为文件系统可以在投入专用接口之前提供灵活性。
但是,文件系统存储有明显的缺点,如弱并发、手动模式强制和原子事务。当你的应用程序需要扩展或转移到多代理场景时,这些问题会变得更加明显。任何忽视这些缺点的人都注定会痛苦地重造更糟糕的数据库,而无法享受生产数据库已经提供的事务安全或访问控制的数十年工程经验。此外,在大多数企业环境中,你无法选择是否使用数据库,因为它已经存在,并存储着关键的业务数据。
Shell 工具是文件系统搜索的自然起点。目前,编码代理正在推动该领域的许多进展。因为它们处理本地文件中的代码,所以自然是文件密集型用例。因此,LLM 在后训练阶段被微调用于编码任务。这就是为什么许多 LLM 不仅擅长写代码,还擅长使用 shell 命令和导航文件系统的原因。
使用内置 CLI(如 ls 和 grep)的 shell 工具来查找文件是有效的。使用 grep,像“查找所有导入了 matplotlib 的文件”这样的查询是快速、精确且便宜的。但是,当代理需要处理概念性查询时,例如“我们的应用程序如何处理身份验证失败?”,使用 grep 进行模式匹配可能很快就会遇到瓶颈。为了解决这个问题,许多带有语义搜索功能的命令行工具如 jina-grep 开始出现。
然而,grep 及其许多语义搜索替代品在整个语料库上运行的复杂度是 O(n)。对于代码库的用例,这可能没问题。但是,如果你的数据增长,延迟将变得显著。在这种情况下,需要一个有索引的数据存储来维持性能。
另一种增加搜索能力(如语义或混合搜索)的方法是将数据存储在数据库中,例如 Cursor 所做的。此外,当数据需要复杂的关系连接或聚合时,数据库接口是不可或缺的。
当数据存在于数据库中而非文件系统上时,shell 工具可以作为某些用例的轻量级数据库接口。如果你的查询足够简单,可以通过 CLI 或 curl 调用来完成,那么专用数据库工具可能会增加不必要的复杂性。
这种方法也适合于早期探索阶段,当你尚不知道代理会发展出什么样的查询模式时。在这种情况下,代理技能可以为代理提供足够的结构,以便在不承诺使用专用工具的情况下正确地进行查询。然而,当代理需要多次迭代才能找出正确的方法来查询数据库以完成重复任务时,使用 shell 工具作为接口的令牌开销不再能证明其简化的好处。
尤其是当重复的查询模式是结构化或分析型的时,专用数据库工具变得必要。一篇来自 Vercel 和 Braintrust 的博客文章比较了不同搜索工具组合的代理在半结构化数据上的真实检索任务(例如,客户支持票据和销售电话记录)中的表现(例如,“有多少个开放问题提到了‘安全’?”或“查找有人报告错误并随后有人提交 PR 声称修复的案例?”)[4]。
拥有专用数据库工具的代理使用的令牌更少,速度更快,错误更少,而只使用 shell 工具和文件系统的代理相对较差。经验教训是,当查询需要对半结构化数据进行分析推理时,直接使用数据库工具是正确的选择。
没有一种搜索接口能很好地处理所有查询。例如,Cursor 结合了 shell 工具(用于通过 grep 搜索)和语义搜索工具,并允许代理根据用户的提示选择合适的工具。他们报告说,代理在匹配特定符号或字符串时选择 grep,在处理概念或行为问题时选择语义搜索,而在探索性任务中选择两者。
Vercel 的实验也报告了同样的结论:其混合代理可以使用 shell 工具和专用数据库工具,以最高的性能完成测试的所有代理任务,首先使用专用数据库工具,然后通过文件系统的 grep 验证结果。然而,这种方法使用了更多的令牌和时间来推理工具选择和验证。
这两个例子的模式都是相同的:组合打败单一接口,但组合带来了额外的成本和延迟。
合适的搜索接口集是小而有目的的,并且特定于代理的实际查询模式。目前的最佳实践是拥有尽可能少的工具,而不是拥有数百个 MCP 工具的代理。因为预先暴露所有可能的工具会使上下文窗口膨胀,并使代理混淆到底应该使用哪个工具。例如,据报道 Claude Code 只有大约 20 个工具。
相反,渐进披露的想法是从最小的工具集开始,并让代理仅在需要时发现额外的功能。Anthropic [5] 和 Cursor [6] 的研究表明,这种方法可以节省 47% 到 85% 的令牌。例如,Claude Code 直接实现了这一点,允许代理逐步发现如何查询 API 或数据库,而不需要在每次 LLM 调用时都消耗上下文。
一旦你熟悉了代理的查询模式,就可以重新审视代理默认访问的搜索工具集。一个有用的思考方式是“低门槛,高天花板”原则,用于决定哪些工具可以入选。高天花板工具不会限制代理的潜力。例如,一个多功能的 shell 工具允许代理编写完整的数据库查询,包括模糊查询,但代价是推理开销较大、延迟较高和可靠性较低。
低门槛工具则相反。它们是专用工具,包装特定查询,可以以最小的推理开销立即供代理访问,成本更低,可靠性更高。但它们需要前期工程,不能涵盖所有可能的查询,并可能使代理更难选择正确的工具。
可以将每个工具视作一个光谱上的点:低门槛工具易于代理正确使用,但范围狭窄。高天花板工具虽然功能多样,但需要更多推理才能很好地使用。

图解比较了三种代理设计方法(高门槛/高天花板、低门槛/低天花板和低门槛/高天花板),展示了不同工具策略如何影响代理处理模糊、灵活和可预测查询。
大多数代理需要混合使用不同的搜索工具。但每个工具都需要证明其存在的合理性。我们建议从通用搜索工具开始(例如 search_database() 工具或 shell 工具)。然后,重用你为安全目的已经保留的命令日志,以跟踪代理实际执行的操作,包括工具调用、重试以及每个用户查询的调用次数。当你发现某个查询模式重复或失败时,就是构建专用工具的信号。
文件系统与数据库的争论分散了工程师们应该关注的问题:代理需要什么样的搜索接口来构建自己的上下文? 答案很可能是,不只一种。
Shell 工具是与不同外部数据源交互的多功能工具,因此是一个良好的起点。但对于具有结构化分析查询的用例,它的效率和准确性低于专用数据库工具。
目标是找到最小的搜索工具集,以良好地处理代理的实际查询模式。从 shell 工具开始,记录代理实际执行的操作。当你看到某个查询模式重复且失败时,就该为其设计专用工具了。
1. Thariq (Anthropic). 从构建 Claude Code 中学习:像代理一样看待 (2026)。
2. Cursor: 文档. 语义与代理搜索 (2026)。
3. Harrison Chase (LangChain). 我们如何构建 Agent Builder 的记忆系统 (2026)。
4. Ankur Goyal (Braintrust) 和 Andrew Qu (Vercel). 测试 “bash 是不是你所需要的一切” (2026)。
5. Anthropic. 在 Claude 开发者平台上引入高级工具使用 (2025)。
6. Cursor. 动态上下文发现 (2026)。
Agent Builder 现已全面上线。通过 Elastic Cloud 试用 开始,查看 Agent Builder 的文档。