RAG 系统进化论(八):Agentic RAG(智能体式 RAG),从回答问题到完成任务

本文导读: Agentic RAG(智能体式 RAG)把系统从执行固定问答流程,推进到自主规划和完成多步骤任务。本文将介绍任务规划、工具选择、多步检索、状态与检查点、并行执行、人工介入、预算和停止条件,理解系统如何根据中间结果调整行动,以及这种自主性带来的新风险。
上一篇的 Multimodal RAG(多模态 RAG)让系统能够检索和理解文本、表格、图片与页面。
但多数 RAG 仍然在执行一条预先设计好的流程:
text
接收问题 → 检索证据 → 生成答案
对于简单问答,这已经足够。
如果用户提出一个开放式任务:
text
分析过去六个月机械键盘退款率上升的原因,
找出受影响最大的产品和地区,
结合售后工单与产品手册提出三个改进建议。
系统不能通过一次检索直接完成。
它需要:
text
查询退款率趋势
→ 找出异常月份
→ 分析产品和地区
→ 检索相关售后工单
→ 查看产品手册和故障说明
→ 验证不同来源是否一致
→ 汇总结论和建议
而且中间结果会改变后续步骤。
如果统计数据表明问题集中在 AX-2048-C,系统才需要继续检索该型号;如果问题集中在物流破损,就应该转向运输数据,而不是继续分析产品故障。
这就是 Agentic RAG 要解决的问题:
让系统围绕一个目标制订计划、选择工具、多步检索,并根据中间结果调整下一步行动。
什么是 Agentic RAG?
Agent(智能体)不是"调用了大模型的聊天机器人",而是一个能够围绕目标反复执行以下循环的系统:
text
观察当前状态
↓
决定下一步行动
↓
调用工具获取新信息
↓
更新状态并检查目标
↓
继续、调整或停止
Agentic RAG 把检索放进这个循环:

Agentic RAG 与 Modular RAG 的区别
Modular RAG(模块化 RAG)也有路由和工具,但主要路径通常由开发者预先定义。
| 对比 | Modular RAG | Agentic RAG |
|---|---|---|
| 输入 | 类型相对明确的问题 | 开放式目标或复杂任务 |
| 执行路径 | 从预设分支中选择 | 根据中间结果持续规划 |
| 工具调用 | 通常执行一次或固定组合 | 可以多轮选择和调用 |
| 停止方式 | 流程到达结束节点 | 判断目标完成或触发限制 |
| 典型场景 | 查政策、查订单、查报表 | 调查、研究、比较和任务执行 |
Agentic RAG 并不是一定更好。
能用固定工作流解决的问题,通常不需要引入自主循环。智能体带来的灵活性,也会增加不确定性、延迟和风险。
Agentic RAG 的完整循环
第一步:Planner 把目标拆成计划
Planner(规划器)把一个开放式目标拆成若干可执行任务。
对于退款率分析,初始计划可能是:
text
任务 1:查询过去六个月总体退款率
任务 2:按产品和地区拆分异常
任务 3:检索异常产品的售后工单
任务 4:查看相关故障手册
任务 5:汇总原因、证据和建议
一份可执行计划不只包含文字说明,还应该包含:
text
任务 ID
任务目标
依赖任务
允许使用的工具
完成条件
当前状态
ts
interface PlanStep {
// 为每个步骤设置稳定标识,便于记录依赖和执行结果
id: string;
// 描述该步骤需要得到的具体信息或结果
objective: string;
// 只有依赖步骤完成后,当前步骤才能执行
dependencies: string[];
// 限制该步骤可以使用的工具范围
allowedTools: string[];
// 明确什么结果表示当前步骤已经完成
completionCriteria: string;
// 保存等待、执行中、完成或失败等状态
status: "pending" | "running" | "completed" | "failed";
}
计划不应该一次生成后永远不变。
当任务 2 发现异常集中在某个固件版本时,系统可以增加"查询该版本发布时间和变更内容"这一步。
第二步:Tool Selection 选择合适工具
Tool Selection(工具选择)根据当前任务,从允许列表中选择检索器或业务工具。
可能的工具包括:
text
query_metrics:查询经营指标
search_tickets:检索售后工单
search_documents:检索产品手册
search_graph:查询实体关系
inspect_page:查看 PDF 页面或图片
get_order_status:查询订单状态
工具需要明确的输入、输出、权限和副作用。
查询文档通常是只读操作;发送消息、修改订单或创建工单会改变外部状态,风险完全不同。
ts
interface AgentTool {
// 工具名称必须来自系统注册表,智能体不能临时创造工具
name: string;
// 说明工具适合完成什么任务,以及不适合做什么
description: string;
// 标记工具是否会改变外部系统状态
sideEffect: "none" | "reversible" | "irreversible";
// 执行前校验结构化参数、用户权限和调用范围
execute(
input: unknown,
context: AgentContext,
): Promise<ToolResult>;
}
模型只负责提出调用建议,真正执行前仍要经过系统校验。
第三步:Multi-step Retrieval 根据结果继续检索
Multi-step Retrieval(多步检索)指后一次查询依赖前一次查询结果。
例如:
text
第一步:
查询退款率最高的产品
→ AX-2048-C
第二步:
查询 AX-2048-C 退款原因
→ E1007、按键失灵、运输破损
第三步:
只针对 E1007 检索工单和产品手册
→ 发现问题集中在固件 v3.2.1
第四步:
查询 v3.2.1 的发布时间和变更记录
这与一次生成多个查询不同。
Multi-Query(多查询)通常针对同一个问题并行扩大召回;多步检索则要先观察前一步,再决定下一步问什么。
ts
async function executePlanStep(
step: PlanStep,
state: AgentState,
) {
// 根据当前步骤目标和已有证据选择允许的工具
const toolCall = await selectTool({
objective: step.objective,
evidence: state.evidence,
allowedTools: step.allowedTools,
});
// 在执行前校验工具名称、参数、权限和副作用
const validatedCall = validateToolCall(
toolCall,
state.user,
);
// 执行工具并获得新的数据、证据或错误
const result = await runTool(validatedCall);
// 将结果写入状态,供后续步骤决定新的检索方向
return updateAgentState(state, step, result);
}
第四步:Memory 与 Checkpointer 保存任务状态
Agentic RAG 可能执行几十秒甚至更长时间,不能只依赖一次模型调用中的上下文。
Memory(记忆)保存任务过程中需要继续使用的信息,例如:
- 用户目标;
- 已完成的步骤;
- 关键中间结论;
- 已收集的证据;
- 工具调用历史;
- 用户补充的信息。
记忆不等于把所有历史原样放入 Prompt(提示词)。
更合理的做法是区分:
text
短期状态:当前计划、最近结果和下一步
长期记忆:跨任务需要保留的用户偏好或业务事实
原始记录:完整工具输入、输出和证据来源
Checkpointer(检查点保存器)把当前 State(状态)持久化,使任务能够暂停、恢复或在失败后从某个节点重试。
ts
async function saveCheckpoint(
state: AgentState,
) {
// 保存当前计划及每个步骤的执行状态
const snapshot = {
plan: state.plan,
currentStepId: state.currentStepId,
evidence: state.evidence,
toolHistory: state.toolHistory,
budget: state.budget,
};
// 使用任务 ID 保存版本化检查点,支持暂停后恢复
await checkpointStore.save(
state.taskId,
snapshot,
);
}
LangGraph(用于构建有状态工作流的框架)可以用状态、节点、边和检查点表达这类长流程,但框架不会自动解决计划质量、权限和停止条件。
第五步:并行处理互不依赖的任务
Parallel Tasks(并行任务)可以同时执行没有依赖关系的步骤。
例如,发现异常产品后,可以并行:
text
检索售后工单
查询固件版本
查看产品手册
按地区统计退款率
ts
async function runReadySteps(
plan: PlanStep[],
state: AgentState,
) {
// 找出依赖已经完成、当前可以执行的步骤
const readySteps = findReadySteps(plan);
// 只并行执行互不依赖且没有写入冲突的只读任务
const results = await Promise.allSettled(
readySteps.map((step) =>
executePlanStep(step, state),
),
);
// 合并成功结果并记录失败步骤,不让单个错误覆盖整个状态
return mergeParallelResults(state, results);
}
会修改同一外部资源的任务不能盲目并行,否则可能产生重复操作和数据冲突。
第六步:Human-in-the-loop 让人参与关键决策
Human-in-the-loop(人在回路中)指系统在关键节点暂停,请求人工确认、修改或接管。
适合人工介入的情况包括:
- 缺少会改变任务方向的重要信息;
- 多个权威来源相互冲突;
- 即将调用会产生外部影响的工具;
- 涉及退款、审批、发送消息等高风险操作;
- 结论置信度低但业务影响大。
text
只读检索产品手册
→ 可以自动执行
根据分析结果创建召回工单
→ 必须人工确认
ts
async function authorizeAction(
call: ToolCall,
) {
// 只读、低风险调用通过自动权限检查后可以执行
if (call.sideEffect === "none") {
return checkReadPermission(call);
}
// 会修改外部系统的调用生成清晰预览并暂停任务
return requestHumanApproval({
tool: call.name,
input: call.input,
expectedEffect: call.expectedEffect,
});
}
人工确认不应该只显示"是否继续",而要明确展示将调用什么工具、使用哪些参数、产生什么影响。
第七步:Budget 与 Stop Condition 控制循环
Agentic RAG 最危险的问题之一,是系统不知道何时停止。
它可能不断:
text
搜索 → 发现新问题 → 再搜索 → 再改计划
Budget(预算)为任务设置资源上限:
text
最大步骤数
最大工具调用次数
最大 Token 数
最大费用
最长运行时间
每个数据源的调用上限
Stop Condition(停止条件)定义何时结束:
text
目标已经完成
关键结论都有证据
没有新的有效信息
达到资源上限
连续多次工具失败
需要人工输入
ts
function shouldStop(
state: AgentState,
): StopDecision {
// 目标的全部完成条件满足时正常结束
if (allObjectivesCompleted(state.plan)) {
return { stop: true, reason: "goal_completed" };
}
// 达到步骤、时间、调用次数或费用上限时强制停止
if (isBudgetExceeded(state.budget)) {
return { stop: true, reason: "budget_exceeded" };
}
// 连续失败或缺少必要输入时暂停并交给用户
if (needsHumanInput(state)) {
return { stop: true, reason: "human_input_required" };
}
// 其他情况下允许进入下一轮规划与执行
return { stop: false };
}
把七个步骤串起来
ts
async function runAgenticRAG(
goal: string,
user: UserContext,
) {
// 根据用户目标生成带依赖、工具范围和完成条件的初始计划
let state = await createAgentState(goal, user);
state.plan = await createPlan(goal);
while (true) {
// 每轮开始前检查目标、预算、失败次数和人工介入条件
const stop = shouldStop(state);
if (stop.stop) {
return finalizeTask(state, stop.reason);
}
// 选择当前可执行步骤,必要时并行调用检索工具
state = await runReadySteps(state.plan, state);
// 根据新证据判断原计划是否需要增加、删除或调整步骤
state.plan = await revisePlan(
state.plan,
state.evidence,
);
// 保存检查点,确保长任务能够暂停和恢复
await saveCheckpoint(state);
}
}
这段流程的重点不是 while 循环,而是每轮都有:
text
明确目标
受控工具
可检查状态
预算限制
停止条件
证据来源
Agentic RAG 引入了哪些技术和方案?
Agentic RAG 把检索放进一个能够持续规划、行动、观察和调整的任务循环。
| 技术 | 主要作用 | 产生的结果 |
|---|---|---|
| Planner(规划器) | 把开放式目标拆成可执行任务 | 带依赖和完成条件的计划 |
| Tool Selection(工具选择) | 根据当前任务选择检索器、API 或数据库 | 结构化工具调用 |
| Multi-step Retrieval(多步检索) | 根据中间结果继续寻找下一批证据 | 逐步扩展的证据集合 |
| Memory(记忆) | 保存任务历史、已有证据和关键决策 | 可复用的任务上下文 |
| Checkpointer(检查点) | 持久化运行状态 | 可暂停和恢复的任务 |
| Parallel Execution(并行执行) | 同时处理没有依赖关系的子任务 | 更短的任务等待时间 |
| Human-in-the-loop(人在回路) | 在高风险或不确定节点请求人工确认 | 审批、修改或补充信息 |
| Budget 与 Stop Condition | 限制步骤、时间、工具调用和费用 | 可控的停止结果 |
常见落地方式可以分成三类。
方案一:有边界的检索智能体
只允许智能体使用少量只读检索工具,并限制最大步骤数。
它适合研究、比较和故障调查,是从普通 RAG 演进到 Agentic RAG 的安全起点。
方案二:可恢复的长任务
text
规划 → 执行 → 保存检查点
↓
暂停、恢复或重新规划
通过 State(状态)、Memory 和 Checkpointer 保存任务进度,适合需要多轮检索、耗时较长的分析任务。
方案三:人工监督的业务智能体
智能体可以准备查询或操作方案,但涉及写数据库、发消息、退款和发布等高风险动作时,必须经过人工审批。
这种方案牺牲了一部分自动化程度,却能显著降低错误操作带来的风险。
Agentic RAG 解决了什么?
1. 支持开放式、多步骤任务
系统不再只回答一个事实问题,而可以执行调查、比较、分析和研究任务。
2. 根据中间结果调整计划
后续检索方向由真实结果决定,而不是在开始时写死。
3. 动态选择工具和数据源
系统可以围绕当前步骤选择数据库、文档、图谱、图片或业务接口。
4. 支持暂停、恢复和人工介入
检查点与 Human-in-the-loop 让长任务具备可控性。
Agentic RAG 还留下了什么问题?
能力越自主,行为越难预测。
错误会在多步中累积
早期步骤选错产品,后续查询、分析和结论可能全部建立在错误前提上。
成本和延迟更加不稳定
不同任务执行的步骤数不同,可能从几次调用增长到几十次调用。
安全边界更加重要
智能体可以选择工具并生成参数,必须防止越权查询、提示词注入、重复操作和未经确认的外部修改。
失败位置更难定位
最终答案错误,可能来自:
text
计划错误
路由错误
工具参数错误
检索错误
证据判断错误
生成错误
停止过早或过晚
只看最终答案,已经无法判断系统在哪里出了问题。
下一篇:RAG 评测与可观测性
下一篇不再增加新的检索能力,而是回答一个更现实的问题:
text
加入查询改写后真的更准了吗?
引入 Reranker 后提升了多少?
智能体为什么调用了错误工具?
一次任务花了多少时间和费用?
错误发生在检索、生成还是工作流节点?
Agentic RAG 让系统能够自主完成多步骤任务。
RAG 评测与可观测性要解决的是:
当系统越来越复杂时,我们怎样用数据证明它变好了,并定位每一次失败发生在哪里?