如果你构建过代理,你就知道上下文工程是让代理返回有意义响应的关键部分。
上下文工程是从所有可能的上下文来源中,决定什么实际进入代理的上下文窗口,以便LLM生成最佳响应的过程。这也被称为"上下文策展"过程,在下图中显示为从可能的上下文来源到上下文窗口的箭头。
我认为我们没有给予这个上下文策展箭头足够的认可,因为它几乎承担了所有繁重工作。隐藏在它后面的是一组代理可以决定使用的搜索工具。这就是为什么我的个人看法是:
上下文工程大约80%是agentic search。
1、历史
让我们退一步,看看AI栈中的搜索在过去三年中是如何从检索增强生成(RAG)演变到agentic search/agentic RAG,再到context engineering的。
1.1 检索增强生成
当我们在2024年首次开始使用LLM构建时,我们开始实现具有固定检索管道的RAG系统:
- 用户消息几乎原封不动地作为搜索查询使用(通常是向量搜索)。
- 从数据库中提取一次分块。
- 检索到的分块与用户消息在提示中组合后送入LLM。
这种设计直观明了,对于狭窄的问答仍然有效。但它也会以可预测的方式出问题,因为你只检索一次:
- 即使模型不需要外部上下文你也检索了,不相关的分块可能让它困惑。
- 你检索一次且没有选项纠正查询。如果返回的结果不包含相关信息怎么办?
- 你检索一次,即使问题需要多跳检索。第一批分块可能只告诉你下一步该搜索什么,但管道不会运行第二遍。
1.2 Agentic RAG
为了克服这些限制,我们用搜索工具替代了固定管道,并称之为"agentic RAG"、“agentic retrieval"或"agentic search”。在这种情况下,代理决定是否调用搜索工具、结果是否相关、是否需要检索更多、以及是否重写搜索查询。
1.3 上下文工程
在上下文工程中,我们现在有许多不同的上下文来源:
- 本地文件(如你的代码仓库、包含
plan.md或todo.md文件的便签本,或Agent Skills), - 数据库(如存储大规模企业数据),
- 网络,
- 长期记忆。
根据上下文来源的不同,我们通常有原生搜索工具:
- 文件搜索用于本地文件,
- skill加载用于Agent Skills,
- 专用数据库工具(语义搜索或查询执行)用于数据库,
- 网络搜索用于网络,
- 记忆工具用于长期记忆。
如果这还不够令人不知所措,我们现在还有一个让代理运行终端命令的工具。这个工具有很多名字:LangChain称之为"shell tool",Anthropic称之为"bash tool",OpenClaw称之为"exec tool"。在下文中,我们将称之为**“shell tool”**。
shell tool是一个多功能工具,因为它可以与大多数上下文来源交互:它可以针对本地文件运行命令(ls、grep)、数据库(CLI、脚本、curl到HTTPS API)和网络(curl)。
这就是为什么目前有很多关于shell tool是否是代理唯一需要的讨论。该博客和本工作坊的核心话题是实际问题不是shell tool与其他工具,而是哪些搜索工具属于你的技术栈。
如果你从本次工作坊中学到一件事,那就是:
做好搜索是困难的。这就是为什么我们有这么多不同的搜索技术,以及为什么你需要为延迟和质量需求策展一个技术栈。
2、构建搜索工具的基础知识
理论上agentic search看起来很简单:
- 用户发出请求
- 代理用正确的参数调用正确的工具
- 工具返回搜索结果
- 代理用正确的答案响应
但在现实中,这可能以许多不同方式出问题。在Elastic,我们帮助团队在Elasticsearch数据上构建代理,我们观察到三个最常见的失败模式:
- 代理根本不调用任何工具,而是从参数知识中回答。
- 代理调用了错误的工具(如网络搜索而不是公司索引)。
- 代理调用了正确的工具但参数错误。
2.1 工具描述
我不喜欢强调这一点,因为我觉得大家都知道工具描述是任何工具最重要的部分。但是当你看到工具描述只是一行简短的描述,而你在想为什么你的代理无法使用它时,让我快速给你一个提醒。
从一个清晰的核心目的和触发条件开始。当你注意到你的代理在使用你的工具时遇到困难,开始添加模板的更多组件,如操作、关系、限制和示例。
如果这还不够,在系统提示中重复相同的规则。
2.2 参数复杂性
另一个需要注意的方面是参数复杂性。因为一旦选择了正确的工具,代理仍然需要填充参数,有些参数比其他参数更容易正确填写。
例如,当ID在消息中时,get_customer_by_id的参数很容易。或者接受任何字符串作为搜索查询的语义搜索工具通常没问题。但当你开始添加更多参数(如过滤器或top_k)时,LLM生成有效参数会变得更具挑战性。
3、代码演练
让我们看看一些搜索工具实现。我们使用LangChain进行编排,因为它抽象了大量复杂性,使我们能够专注于高层概念,并且它提供了shell工具和其他有用的东西。
对于演示,我们使用AI Engineer Europe 2026日程数据集进行搜索。
3.1 Vanilla agentic search
让我们回顾一下第一个notebook中实现的最小vanilla agentic search设置。它由索引conference_schedule上的一个语义搜索工具组成,每个文档对应一个session。
这里我们设置了LLM,这是任何代理的核心。然后定义了一个最小的系统提示,告诉代理它是一个搜索代理。接下来准备Elasticsearch客户端,定义搜索工具。LangChain的@tool装饰器让我们将任何Python函数转换为代理工具。
对于语义搜索查询"哪些session讨论AI系统中的监管约束?",代理现在调用工具并正确找到了Bilge Yücel关于在主权约束下工程AI的演讲。
这是大多数agentic search演示停止的地方。这也是它开始变得有趣的地方。
要打破这个基于语义搜索工具构建的演示,你只需要问一些关键词搜索比语义搜索更合适的问题。例如,如果我问"我应该参加哪些session来了解更多关于GEPA的内容?",语义搜索返回不相关的session,但没有找到正确的那个。
3.2 带通用数据库搜索工具的Agentic search
如果代理能够完全自主地从零开始编写整个搜索查询呢?让我们用更通用的工具(execute_esql_query)替代窄范围的语义搜索工具。
首先我们从gpt-5.4-nano切换到gpt-5.4-mini,因为查询生成比传递主题更困难。
然后我们定义一个通用数据库查询工具,让代理针对Elasticsearch运行完整的ES|QL查询。需要注意的是,我们还添加了一个try/except块,如果ES|QL查询抛出错误则返回一些有意义的信息,以便代理可以自我纠正。
当我们运行同样的问题"我应该参加哪些session来了解更多关于GEPA的内容?"时,代理生成的ES|QL查询看起来是有效的,但返回零搜索结果,因为%GEPA%使用的是SQL中的%通配符,而ES|QL使用*通配符。
有很多方法可以解决这个问题,比如改进指令或添加ES|QL特定的agent skills。对于本教程,我们将定义一个最小的skill。
现在代理首先调用ES|QL skill并使用它来编写有效的ES|QL查询。结果表明,这种方式代理能够找到正确的session。
由于这个工具是通用目的的,代理还可以将其用于分析问题,比如通过使用STATS来查询"4月8日有多少个session?"
3.3 带shell tool的Agentic search
最后,让我们谈谈agentic search目前最热门的话题:“Bash + Filesystem是你需要的一切”。
对于这个实现,我们将相同的数据从Elasticsearch集群移动到本地文件,并让代理使用LangChain的ShellTool进行搜索。
首先我们实例化shell tool。请注意,shell tool默认没有任何安全保护措施,建议仅在沙箱环境中使用。
这个例子的系统提示与之前描述的类似,只是我们现在描述的是文件系统中的数据而不是Elasticsearch集群中的数据。
原文链接:没有搜索,就没有上下文工程 - 汇智网