直接回答
Agentic RAG 是一种由 AI 智能体 决定是否检索、检索哪里以及迭代几次的检索增强架构,而不是执行一次固定搜索。生产环境的核心单元不是不受约束的“思考循环”,而是有边界的证据控制循环:检索工具必须经过授权并返回类型化结果,证据保留来源,系统限制迭代、Token 和时限,并用明确终态决定基于充分证据生成、向用户澄清或拒答。只有当它相对强固定 RAG 基线提升验收答案或 Goodput 时,智能体化才创造了价值。
核心要点
- 检索下沉为策略控制的工具,但 LLM 选中了某份材料,不代表材料可信。
- Self-RAG、CRAG 与 Adaptive-RAG 是不同研究方法,不能把任何“带评分器的循环”都冠以这些名称。
- 循环必须显式限制步骤、工具、Token、时限、证据时效与副作用。
- LLM 评分只是噪声信号,不能授予权限、证明事实有依据,也不能清除提示词注入。
- 上线前应分别评估路由、检索、证据、答案、拒答、安全和运行效率。
什么让 RAG 具备智能体特征?
当检索决策从固定应用流程下沉到运行时控制策略,RAG 才具备智能体特征。标准 RAG 本来就可以包含混合检索、重排、元数据过滤与引用;Agentic RAG 额外引入以下条件决策:
- 跳过检索、检索一个数据源,或查询多个已授权数据源;
- 将多部分问题分解为证据任务;
- 在检索失败时改写查询,但不改变用户目标;
- 检查已取回证据的缺口与冲突;
- 结束、澄清、拒答,或执行下一次有边界的检索。
这一定义不要求展示思维链、不要求多智能体,也不绑定某个框架,但必须具备状态和条件控制。Agentic RAG 综述 给出的分类维度比常见营销文章更广,包括智能体数量、控制结构、自主程度与知识表示。因此,“路由、多步、纠错、适应性”只是常用示例,不是业界公认且穷尽所有系统的四种标准模式。
该循环属于 Agentic Workflow,但检索仍是有独立契约的只读操作。修改订单、发起退款等业务动作应使用不同工具,并配置独立授权、确认、幂等与审计策略。
不同研究方法对应不同契约
高频出现的适应性检索方法解决的是不同问题。把它们当成同义词,会产生错误实现和不成立的效果声明。
| 方法 | 核心机制 | 不能据此证明什么 |
|---|---|---|
| Self-RAG | 训练同一个模型按需检索,并生成关于相关性、支持度与效用的反思 Token | 普通提示词评分器不自动等于 Self-RAG |
| CRAG | 通过检索评估器与置信度触发不同纠错动作;论文还探索了 Web 搜索与文档精炼 | 一个二分类“相关性”提示词不能复现论文,也不保证纠错有效 |
| Adaptive-RAG | 使用训练得到的复杂度分类器,在无检索、单步检索和迭代检索之间选择 | 手写“简单/复杂”提示词不能继承论文实验结果 |
| Agentic RAG | 智能体在控制策略下选择并迭代检索工具的系统模式 | 该标签本身不保证质量、延迟、安全或成本 |
Self-RAG 的关键是训练模型生成特殊反思 Token。调用多个普通模型 API 来批评答案,可以称为提示词驱动的自反思编排,但不等于论文中的训练方法。
Corrective RAG 评估检索质量,并根据评估结果选择不同纠错动作。评估器仍会出错;如果回退到外部 Web 搜索,系统还改变了信任、授权、时效和引用边界。
Adaptive-RAG 根据任务结果与数据集信号学习问题复杂度分类器。无检索、单步和迭代三条路径属于该论文实验设计,并非对所有业务问题都成立的通用分类。
论文结论只对其模型、数据集、检索器和评测协议负责。工程团队可以学习机制,但必须重新建立本地证据。
把检索工具设计为安全边界
检索工具应是应用拥有的接口,而不是裸数据库连接或任意 URL 抓取器。输入输出 Schema 要显式表达授权与证据契约。
{
"name": "search_support_runbooks",
"purpose": "检索当前租户可访问的已审核运维手册",
"input": {
"query": "string",
"tenant_id": "服务端注入",
"product": "白名单枚举",
"top_k": "1 到 8 的整数"
},
"output": {
"evidence": [
{
"source_id": "不可变文档 ID",
"revision": "不可变版本",
"title": "展示标题",
"excerpt": "长度受限的文本",
"retrieved_at": "时间戳",
"acl_scope": "授权范围"
}
]
},
"limits": {
"timeout_ms": 1500,
"max_result_bytes": 40000
}
}
微软当前的 Agentic RAG 架构指南 同样强调明确工具描述、类型化参数、返回 Schema、元数据与过滤器。这些约束能改善工具选择,但服务端仍须在模型之外推导身份与租户范围。
授权必须发生在检索之前
智能体不得自行填写 tenant_id、访问过滤器、数据库名或凭据。应用从认证上下文推导范围,在搜索前将请求与策略求交集。文档级授权应先于排序执行,避免未授权候选影响分数、日志、缓存或模型上下文。
2026 年一项多租户检索研究把这个问题形式化为相关性与授权之间的缺口:稠密、稀疏和混合检索器优化的是相关性,而不是访问权限。该研究的实验系统在构造上下文前执行基于属性的授权谓词,从而阻止跨租户暴露;具体结果只属于其实现,但架构结论可以复用:后端支持时,应把授权下推到候选生成阶段。先取全局 Top-K 再过滤,既可能泄漏 Metadata,也可能因为合法文档排在越权文档之后而破坏 Recall。
检索内容是不可信数据
文档、网页、工单与工具输出都可能包含提示词注入。系统应隔离证据、保留来源身份,并明确检索文本无权改变系统策略或授权新工具。删除“忽略此前指令”等关键词不是安全边界;真正的边界是代码层对白名单工具、参数、目的地、数据量与副作用的强制约束。
每次变换都必须保留来源
查询改写、切块、重排、摘要与去重都可能切断来源链。每条证据需要不可变来源与版本,并维护生成声明到支持片段的映射。仅保存 URL 不够,因为其内容可能变化。
建立有边界的证据控制循环
生产循环必须具备明确状态和状态转移。“一直继续直到模型有信心”不是停止策略,因为模型置信度既未必校准,也无法强制执行。
状态契约
至少记录:
- 请求、用户可见目标、身份范围与策略版本;
- 规划版本与证据任务;
- 每个工具名、归一化参数、结果 ID、耗时与故障;
- 累计步骤、检索、模型调用、Token、墙钟时间与成本;
- 证据覆盖、冲突、时效与授权状态;
- 停止原因,以及最终每条声明实际使用的证据。
默认不要记录完整敏感提示词或文档。应保存脱敏引用,并让原始内容访问具备用途限制、时间限制与审计。
预算契约
执行前设置硬限制:
| 预算 | 避免的问题 |
|---|---|
| 总步骤数与单工具调用数 | 无限改写或搜索循环 |
| 墙钟截止时间 | 用户或网关超时后请求仍在运行 |
| 输入与输出 Token | 上下文和账单失控 |
| 结果字节数与证据条数 | 上下文灌入和内存压力 |
| 单数据源重试次数 | 持续冲击故障依赖 |
| 外部域名白名单 | 任意联网与数据外泄 |
NVIDIA 当前的 Agentic RAG Blueprint 默认关闭智能体路径,并建议按请求启用,因为额外规划与验证会增加模型调用和延迟。它的具体实现属于厂商版本,但通用边界成立:只有复杂请求需要额外控制时,才应支付这部分成本。
停止契约
循环应收敛到少量机器可读终态:
answered
clarification_required
insufficient_evidence
conflicting_evidence
authorization_denied
budget_exhausted
dependency_failed
policy_blocked
“用已有上下文强行生成”是不安全的。证据不足或互相冲突时,应返回缺口与安全的下一步。系统可以输出部分答案,但必须把有依据的声明与未知项明确分开。
可运行的轨迹门禁
以下无第三方依赖的 Go 程序在结果晋级前检查执行轨迹。它不判断事实真假,而是强制校验 Policy Identity、工具与数据源授权、预算、唯一 Evidence ID、终态和声明级证据绑定;这些确定性不变量不允许被 LLM 覆盖。
package main
import (
"errors"
"fmt"
)
var terminalReasons = map[string]bool{
"answered": true,
"clarification_required": true,
"insufficient_evidence": true,
"conflicting_evidence": true,
"authorization_denied": true,
"budget_exhausted": true,
"dependency_failed": true,
"policy_blocked": true,
}
type Policy struct {
Revision string
MaxSteps int
MaxTokens int
AllowedTools []string
AllowedScopes []string
}
type Evidence struct {
ID string
Revision string
Scope string
}
type Step struct {
Tool string
Tokens int
Evidence []Evidence
}
type Claim struct {
Text string
EvidenceIDs []string
}
type Result struct {
StopReason string
Claims []Claim
}
type Trace struct {
Policy Policy
Steps []Step
Result Result
}
func contains(values []string, target string) bool {
for _, value := range values {
if value == target {
return true
}
}
return false
}
func validate(trace Trace) error {
if trace.Policy.Revision == "" {
return errors.New("missing policy revision")
}
if trace.Policy.MaxSteps < 1 || trace.Policy.MaxTokens < 1 {
return errors.New("invalid budget")
}
if len(trace.Steps) > trace.Policy.MaxSteps {
return errors.New("step budget exceeded")
}
totalTokens := 0
evidenceIDs := make(map[string]bool)
for _, step := range trace.Steps {
if !contains(trace.Policy.AllowedTools, step.Tool) {
return fmt.Errorf("unauthorized tool: %s", step.Tool)
}
if step.Tokens < 0 {
return errors.New("negative token count")
}
totalTokens += step.Tokens
for _, item := range step.Evidence {
if item.ID == "" || item.Revision == "" {
return errors.New("evidence identity is incomplete")
}
if evidenceIDs[item.ID] {
return fmt.Errorf("duplicate evidence id: %s", item.ID)
}
if !contains(trace.Policy.AllowedScopes, item.Scope) {
return fmt.Errorf("unauthorized evidence scope: %s", item.Scope)
}
evidenceIDs[item.ID] = true
}
}
if totalTokens > trace.Policy.MaxTokens {
return errors.New("token budget exceeded")
}
if !terminalReasons[trace.Result.StopReason] {
return errors.New("invalid stop reason")
}
if trace.Result.StopReason == "answered" && len(trace.Result.Claims) == 0 {
return errors.New("answered result has no claims")
}
for _, claim := range trace.Result.Claims {
if claim.Text == "" || len(claim.EvidenceIDs) == 0 {
return errors.New("claim has no support")
}
for _, id := range claim.EvidenceIDs {
if !evidenceIDs[id] {
return fmt.Errorf("claim cites unknown evidence: %s", id)
}
}
}
return nil
}
func fixture(scope, citation string) Trace {
return Trace{
Policy: Policy{
Revision: "policy@sha256:7d2e",
MaxSteps: 2,
MaxTokens: 600,
AllowedTools: []string{"search_runbooks"},
AllowedScopes: []string{"tenant:42"},
},
Steps: []Step{{
Tool: "search_runbooks",
Tokens: 240,
Evidence: []Evidence{{
ID: "runbook:refunds",
Revision: "sha256:91af",
Scope: scope,
}},
}},
Result: Result{
StopReason: "answered",
Claims: []Claim{{
Text: "A manager must approve this refund.",
EvidenceIDs: []string{citation},
}},
},
}
}
func main() {
valid := validate(fixture("tenant:42", "runbook:refunds")) == nil
unauthorized := validate(fixture("tenant:99", "runbook:refunds")) != nil
unknownCitation := validate(fixture("tenant:42", "runbook:missing")) != nil
fmt.Printf(
"valid=%t unauthorized_scope_rejected=%t unknown_citation_rejected=%t\n",
valid,
unauthorized,
unknownCitation,
)
}
执行 go run agentic_rag_trace_gate.go,预期输出:
valid=true unauthorized_scope_rejected=true unknown_citation_rejected=true
轨迹如果使用未授权工具或数据源、超过步骤或 Token 预算、重复 Evidence ID、引用未知证据,或返回非法终态,就会被拒绝。内容质量与证据蕴含仍需在独立评测阶段完成。
分层评测 Agentic RAG
Agentic RAG 必须定位结果究竟在哪一层改善或失败。单一 LLM-as-judge 总分会遮蔽路由、检索、证据、生成与运行故障。
| 层级 | 示例指标 |
|---|---|
| 路由与规划 | 工具选择准确率、分解覆盖、非必要检索率 |
| 检索 | Recall@k、nDCG/MRR、过滤正确性、授权结果率 |
| 证据 | 声明覆盖、冲突识别、时效、引用蕴含 |
| 答案 | 任务验收、正确性、完整性、校准后的拒答 |
| 安全 | 跨租户泄漏、提示词注入抵抗、禁用工具尝试 |
| 运行 | TTFT、端到端延迟、工具/模型调用、Token、故障恢复 |
| 效率 | 在 SLO 内单位时间或成本的验收答案数 |
LLM-as-judge 可以辅助评估开放式输出,但必须用人工标签校准,测试位置与表达风格偏差,并保留确定性检查。评分模型绝不能授权数据访问或业务动作。
建立查询切片
版本化评测集至少覆盖:
- 单数据源事实检索;
- 多数据源比较;
- 具有已知证据链的多跳问题;
- 应向用户澄清的歧义请求;
- 应拒答的不可回答请求;
- 过期、冲突或已撤销文档;
- 租户边界问题与未授权干扰项;
- 检索内容中的提示词注入;
- 依赖超时与部分结果。
至少比较三种变体:强固定 RAG、只有路由但无迭代的 RAG,以及完整有边界循环。消融实验可以回答查询分解、纠错或验证是否值得新增成本。
衡量 Goodput,而非原始完成量
只有同时满足答案质量、引用、授权与延迟目标的请求才算有效。增加检索步骤可能提高某个离线答案分数,却因超时或预算耗尽降低用户可见 Goodput。
2026 年的 智能体编排适应性 RAG 研究 报告:分解在一个结构化领域有帮助,却降低了多跳基准的排序精度;反思提高引用准确性,但显著增加延迟。这不是通用基准,却有力说明每个智能体组件都需要按查询切片做消融。
Google 2026 年的跨语料 Agentic RAG 评测提供了另一组有边界的证据:在包含 2,676 份 PDF 的 824 条 FramesQA 查询中,Planner 从 4 个语料库中选源,报告 90.1% 答案准确率,平均延迟与单语料配置相差不超过 3%。该实验使用特定托管系统和 LLM Judge,不能把分数复制成发布阈值;应在自有语料上复现实验,保留固定 RAG 对照,并把路由错误与答案错误分开审阅。
观测决策,而不是暴露敏感内容
有用轨迹应解释系统做了什么,同时避免默认保存完整提示词。
应采集:
- 策略、Prompt、模型、检索器、索引与语料版本;
- 被选工具与归一化参数;
- 来源 ID、版本、分数、过滤器与授权范围;
- 路由、改写、纠错、停止原因和预算计数器;
- 引用映射与输出 Schema 校验;
- 每一步延迟、Token、重试、缓存状态与错误。
遥测前应脱敏密钥与个人信息,限制原始证据访问,并按用途设置保留期。可以把轨迹接入 智能体可观测工作流,但不要把模型生成的解释当作权威内部轨迹。
把上线设计成可逆策略变更
Agentic RAG 同时改变答案行为与资源消耗,应该按查询切片或租户发布,而不是不可逆地替换所有请求。
- 冻结基线、语料、索引和评测集。
- 离线回放轨迹并审阅分歧。
- 影子运行智能体策略,但不向用户返回其答案。
- 只对存在明确故障、且循环能够解决的查询切片灰度。
- 质量、泄漏、延迟、Token 或依赖错误回归时自动回滚。
- 持续保留固定路径,关闭循环不应依赖重新构建系统。
常见失败模式
把评分器当成事实真值
评分器可能误解问题、偏好冗长文档,或服从检索内容中的注入指令。应使用有标签的检索数据、确定性元数据检查与经过校准的阈值,并把不确定案例路由到澄清或人工审核。
没有新信息却反复重试
针对同一索引改写同义句,可能只消耗预算而不改善召回。记录检索签名,并要求下一轮在数据源、过滤器、查询或待补证据上发生实质变化。
查询分解后丢失授权
子查询必须继承原用户范围。规划器请求了更宽范围,不代表可以扩大租户、时间、项目或数据分级。
引用了检索文本,但文本不支持声明
文本出现在上下文中不等于支持答案。每个关键声明都应由引用片段蕴含;证据冲突时应暴露冲突,而不是选择最方便的一份。
混合检索与副作用
查询订单和发起退款是两种能力。检索证据可以支撑行动建议,但业务动作需要独立授权、确认、幂等和结果对账。
常见问题
Agentic RAG 一定优于固定 RAG 吗?
不一定。一次授权搜索可以解决问题时,固定流程更容易测试,延迟和成本也更低。只有动态选源、分解或纠错在目标查询切片上产生实测收益,且通过延迟和成本门禁时,才应启用智能体路径。
Agentic RAG 能消除幻觉吗?
不能。更多检索与自评仍可能选择无关证据、服从注入内容、引用不支持答案的片段,或综合出错误结论。系统必须做声明级支持检查,覆盖不可回答案例,校准拒答,并对高影响决策保留人工审核。
内部检索失败后,是否应该自动搜索公网?
只有策略明确允许时才可以。公网搜索会改变数据分级、来源质量、时效、版权、隐私和提示词注入风险。应设置域名白名单、保留引用、标记外部证据,并严禁把敏感内部上下文发送给公网搜索工具。
Agentic RAG 应允许多少次检索?
不存在通用次数。应根据代表性轨迹、用户截止时间、依赖容量和 Token 预算确定上限,同时设置全局硬限制和更小的单工具或单证据缺口限制,并持续监控预算耗尽终态。
系统何时应该澄清或拒答?
缺少一个用户选择就能安全消除歧义时,应请求澄清;所需证据缺失、冲突、未授权、超过时效,或无法在预算内获得时,应拒答。不能把这些状态包装成自信陈述。
总结
Agentic RAG 适用于检索本身需要运行时决策的场景,但“自主”不是目标。真正目标是在明确质量、授权、延迟与成本约束下提升验收答案。工程上应把检索建模为类型化且经过授权的工具,保留证据来源,限制所有循环,在证据失败时安全终止,分层对比强基线,并把上线设计成可回滚策略。
参考资料
- Agentic Retrieval-Augmented Generation: A Survey on Agentic RAG
- Self-RAG: Learning to Retrieve, Generate, and Critique through Self-Reflection
- Corrective Retrieval Augmented Generation
- Adaptive-RAG: Learning to Adapt Retrieval-Augmented LLMs through Question Complexity
- Microsoft:Develop an Agentic RAG Solution
- NVIDIA RAG Blueprint:Agentic RAG
- Google Research:跨语料 Agentic RAG
- Securing the Agent:多租户检索与工具调用
- RAG 原理与评测指南
- 混合检索与重排优化