尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

从生成文本到执行任务:Agent闭环机制与ReAct、AgentExecutor、@tool、RAG实战

发布时间:2026/9/29 18:34:07

资讯中心
01
ARTICLE

从生成文本到执行任务:Agent闭环机制与ReAct、AgentExecutor、@tool、RAG实战

从生成文本到执行任务:Agent闭环机制与ReAct、AgentExecutor、@tool、RAG实战
1. 从“会说话”到“能干活”Agent 到底跨过了哪条分界线很多人第一次接触 Agent 这个概念时脑子里浮现的画面是“一个更聪明的聊天机器人”。我刚开始也是这么想的直到我真正动手把一个只会生成文本的模型改造成能自己决定调用哪个工具、自己读文件、自己跑命令、自己判断任务是否完成的东西才意识到这两者之间隔着的不是一点半点而是一整条工程化的鸿沟。这篇笔记的核心就是记录我如何理解并实现“Agent 从生成文本到执行任务”这个跨越。关键词里出现的 Agent、ReAct、AgentExecutor、tool、RAG基本就是这条路径上的五块基石。如果你正在学 Agent 开发或者已经写过一些调用大模型的代码但总觉得“差点意思”那这篇内容应该能帮你把脑子里那些零散的概念串成一条线。我会尽量用从业者之间聊天的口吻把每一步为什么这么做、坑在哪里、怎么绕过去讲清楚而不是甩一堆术语让你自己猜。先说结论性的判断生成文本和执行任务本质区别在于“闭环”。纯生成是开环的——你给输入它给输出对不对、能不能用它不管。执行任务是闭环的——它要观察环境、做决策、采取行动、拿到反馈、再决策直到目标达成或者确认无法达成。这个闭环就是 Agent 的灵魂。而 ReAct、AgentExecutor、tool 这些都是为这个闭环服务的具体机制。我见过不少朋友卡在“我知道要循环调用但不知道怎么让模型知道有哪些工具、怎么解析它的调用意图、怎么把结果喂回去”这些细节上。这篇就按我自己的实操顺序从整体设计思路讲到核心机制再讲到完整实现和踩坑排查尽量把每个环节都摊开说。2. 整体设计思路为什么是 ReAct AgentExecutor tool 这套组合2.1 先想清楚Agent 的“大脑”和“手脚”怎么分工在动手之前我习惯先把架构想明白。Agent 这套东西说白了就是给大模型装上“手脚”和“眼睛”。大模型本身是大脑负责理解和推理工具是手脚负责实际干活而环境反馈是眼睛负责告诉大脑干得怎么样。那问题来了大脑怎么知道有哪些手脚可以用怎么决定用哪个用完怎么把结果告诉大脑这三个问题分别对应工具注册、决策机制、结果回传。ReAct 解决的是决策机制tool 解决的是工具注册AgentExecutor 解决的是整个循环的调度和结果回传。我选择 ReAct 而不是别的范式理由很实际它把“推理”和“行动”显式地交替进行。Reason 一步Act 一步Observe 一步再 Reason。这种交替的好处是模型在每一步行动前都有机会重新审视当前状态而不是一次性规划完所有步骤然后闷头执行。后者在真实环境里很容易翻车因为环境是会变的第一步的结果可能让原计划完全失效。ReAct 这种“走一步看一步”的方式虽然看起来没那么“智能”但在实际任务里鲁棒性高得多。2.2 AgentExecutor 不是可有可无的包装它是循环的发动机很多人第一次看到 AgentExecutor 会觉得它就是个壳把模型和工具包在一起而已。我一开始也这么以为直到我自己手写了一个简化版的循环才发现 AgentExecutor 帮我处理了多少脏活。它至少干了这几件事解析模型输出里的工具调用意图、校验工具名和参数、执行工具、捕获异常、把结果格式化后塞回对话历史、判断是否达到终止条件、控制最大迭代次数防止死循环。这些事单拎出来都不难但串在一起还要处理各种边界情况就很烦。AgentExecutor 把这些标准化了让我能专注在工具设计和提示词上。我自己的经验是初期不要急着替换 AgentExecutor先用它把流程跑通等真正遇到它满足不了的需求时再考虑自定义。我见过有人一上来就自己写循环结果在异常处理和终止条件上反复踩坑进度反而慢。2.3 tool 装饰器让工具注册变得“无感”工具注册这件事早期我是手动维护一个字典把工具名映射到函数。后来发现这种方式有两个问题一是容易写错名字二是工具的元信息描述、参数 schema要单独维护很容易和函数实现脱节。tool 装饰器的价值在于它把函数的签名和 docstring 直接转成模型能理解的工具描述。我只需要正常写一个函数加上装饰器工具就注册好了。模型的提示词里会自动带上工具名、描述、参数说明。这种“实现即文档”的方式大幅降低了维护成本。不过这里有个坑我踩过docstring 的质量直接决定模型会不会正确使用这个工具。我写过一个工具docstring 只写了一句“查询数据”结果模型经常在不需要的时候调用它。后来我把 docstring 改成“根据用户 ID 查询订单状态仅在用户明确询问订单时使用”调用准确率立刻上来了。所以别把 docstring 当注释写它是给模型看的说明书。2.4 RAG 在 Agent 里的位置不是替代是补充RAG 和 Agent 经常被放在一起讨论但我觉得它们解决的是不同层面的问题。RAG 解决的是“知识从哪来”Agent 解决的是“任务怎么完成”。一个 Agent 可以有 RAG 能力也可以没有一个 RAG 系统可以是 Agent 的一个工具也可以独立存在。在我的设计里RAG 是作为工具之一接入的。当模型判断需要查资料时它调用检索工具拿到相关文档片段再基于这些片段继续推理或生成回答。这样做的好处是检索的时机由模型自己决定而不是每轮都强制检索。实测下来这种方式在多轮对话里更自然也不会因为无关检索拖慢响应。3. 核心细节解析ReAct 循环、工具调用与结果回传的实操要点3.1 ReAct 循环的每一步到底发生了什么我把 ReAct 循环拆成四个阶段来看这样更容易理解每一步的输入输出。第一阶段是思考。模型拿到当前对话历史和可用工具列表输出一段推理文本说明它打算做什么。这段文本不执行任何操作纯粹是“想”。我一开始觉得这步多余后来发现它很有用它让模型的决策过程变得可观测出问题时我能看到它是在哪一步想歪的。第二阶段是行动。模型在思考之后输出一个结构化的工具调用请求包含工具名和参数。这里的关键是格式要稳定否则解析会失败。我用过的框架里有的用 JSON有的用特定标记语言各有优劣。JSON 的好处是通用坏处是模型偶尔会输出不合法 JSON标记语言的好处是解析简单坏处是模型可能不按格式来。我的经验是在提示词里给一两个例子比单纯描述格式有效得多。第三阶段是观察。工具执行完结果被格式化后塞回对话历史。这里要注意结果的长度控制。我有一次让工具返回了一整篇文档结果直接把上下文撑爆了后续推理质量急剧下降。后来我改成只返回关键片段或者做摘要后再返回效果好很多。第四阶段是判断。模型看到观察结果后决定是继续调用工具还是给出最终答案。这个判断也是模型自己做的AgentExecutor 只负责在模型输出最终答案时终止循环。3.2 工具设计的三个原则单一职责、描述清晰、容错友好工具设计是我踩坑最多的地方总结下来有三条原则。单一职责一个工具只做一件事。我写过一个“处理用户请求”的工具里面根据参数不同走了好几条分支结果模型经常传错参数因为它搞不清这个工具到底干嘛的。后来我拆成三个独立工具每个工具名和描述都很明确调用准确率明显提升。描述清晰前面提过 docstring 的重要性这里再强调一次。描述里要写清楚这个工具做什么、什么时候用、参数是什么含义、返回什么。我现在的习惯是描述里至少包含一个使用场景的例子。容错友好工具执行失败时返回的错误信息要能让模型理解并调整。我早期工具报错就抛异常结果整个循环崩了。后来改成捕获异常返回一段“执行失败原因是 XXX建议尝试 YYY”的文本模型看到后往往能自己换个方式重试。这个改动让整个系统的鲁棒性上了一个台阶。3.3 结果回传的格式别让模型猜工具执行结果回传给模型时格式很重要。我试过直接返回原始 JSON也试过返回自然语言描述最后发现结构化但带自然语言说明的混合格式效果最好。比如查询订单的工具返回这样一段订单查询结果 - 订单号12345 - 状态已发货 - 预计送达3 天内比返回{order_id: 12345, status: shipped, eta: 3 days}要好因为模型不需要额外解析就能理解。当然如果后续还要做程序化处理那另说。但在 Agent 循环里模型是消费者所以格式要迁就模型的理解习惯。3.4 最大迭代次数不是限制是保护AgentExecutor 有个参数叫 max_iterations我一开始设得很大觉得让模型多试几次没坏处。结果有一次遇到一个模型死活解决不了的问题它就在那里反复调用同一个工具烧了一堆 token 才停。后来我把这个值设成 10 左右并且在提示词里告诉模型“如果尝试多次仍无法完成请直接说明困难”情况就好多了。这个参数的本质是成本控制和安全阀。Agent 的自主性越强越需要这种硬性边界。我现在的习惯是根据任务复杂度设 5 到 15 之间简单任务 5 次足够复杂任务给到 15 次。4. 完整实操从零搭一个能查资料、能算数、能执行命令的 Agent4.1 环境准备与依赖选择我用的技术栈是 Python LangChain 生态。选它不是因为它是唯一选择而是因为它的 AgentExecutor、tool 这些抽象比较成熟文档也相对全。如果你用别的语言或框架思路是一样的只是 API 名字不同。依赖安装很简单pip install langchain langchain-openai如果你要用本地模型把 langchain-openai 换成对应的集成包就行。我建议初期用 API 模型因为本地模型在工具调用的格式遵循上往往不够稳定调试起来会多一层干扰。4.2 定义三个基础工具检索、计算、执行我设计了三个工具来覆盖常见需求一个 RAG 检索工具、一个计算器工具、一个执行 shell 命令的工具。前两个安全第三个有风险所以我会加上白名单限制。检索工具的实现思路是接收一个查询字符串在向量库里做相似度搜索返回最相关的几个片段。这里的关键是返回片段的数量和长度要控制我一般返回 top 3每个片段截断到 500 字以内。计算器工具我直接用 Python 的 eval 加白名单只允许数学表达式。这里要小心不要直接 eval 用户输入一定要做字符过滤。执行命令的工具我限制得比较严只允许特定前缀的命令比如ls、cat、echo。这是为了防止模型执行危险操作。我见过有人不加限制结果模型自己决定删文件虽然概率低但一旦发生就是灾难。4.3 用 tool 注册工具并生成提示词每个工具用 tool 装饰器包一下docstring 写清楚。然后把这些工具传给 AgentExecutor它会自动把工具信息注入到提示词里。我实测下来工具数量控制在 5 个以内时模型的调用准确率最高。超过 10 个模型开始混淆工具的情况明显增多。如果确实需要很多工具可以考虑分组或者用路由机制先选工具类别再选具体工具。4.4 跑通第一个完整循环第一次跑通的时候我让它做一个复合任务“查一下我们知识库里关于 ReAct 的内容然后算一下这段内容有多少个字”。它先调用了检索工具拿到内容然后调用了计算器工具最后给出了答案。整个过程没有我干预那一刻确实有点小激动。但紧接着就遇到了问题它有时候会跳过检索直接算或者算的时候把标点也算进去导致结果不准。这些都需要通过调整提示词和工具描述来优化。4.5 加入 RAG 后的效果变化加入 RAG 工具后Agent 能回答的问题范围明显扩大了。以前它只能靠自身知识回答现在可以查内部文档。但我也发现一个新问题它有时候会过度依赖检索明明自己知道的问题也要去查一下。后来我在提示词里加了一句“如果问题属于常识范围可以直接回答不必检索”这种情况就少了很多。5. 常见问题与排查技巧实录5.1 工具调用格式解析失败怎么办这是最常见的问题。模型输出的工具调用请求不符合预期格式解析器报错。我的排查顺序是先看模型原始输出是什么再对照提示词里的格式说明看是不是说明不够清楚。大多数情况下加一两个格式示例就能解决。如果还不行可能是模型能力问题换一个更强的模型试试。5.2 模型反复调用同一个工具这种情况通常是工具返回的结果没有让模型满意或者模型陷入了某种循环。我的处理方式是在工具返回结果里加入“如果此结果不满足需求请尝试其他方式”的提示同时在 AgentExecutor 层面设置最大迭代次数。另外检查工具描述是否准确有时候模型反复调用是因为它以为这个工具能解决但实际上不能。5.3 上下文被工具结果撑爆前面提过工具返回结果太长会挤占上下文。我的做法是在工具内部做截断或摘要只返回关键信息。如果确实需要返回长内容可以考虑分页返回让模型决定是否获取更多。5.4 模型不调用工具直接回答这通常发生在模型认为自己知道答案的情况下。如果希望它必须调用工具可以在提示词里明确要求“对于此类问题必须先调用检索工具”。但也要注意过度强制会导致它在不需要的时候也调用增加延迟和成本。5.5 排查速查表问题现象可能原因排查方向解决思路解析失败格式不符看原始输出加格式示例反复调用结果不满意看工具返回优化返回内容上下文溢出结果太长看 token 数截断或摘要不调用工具模型自信看提示词明确要求调用调用错工具描述不清看工具描述细化使用场景5.6 几个我踩过的坑第一个坑是工具名用中文。我一开始觉得中文名更直观结果模型在生成调用请求时经常把工具名写错。后来全改成英文问题消失。第二个坑是参数类型不匹配。模型有时候会把数字传成字符串导致工具内部报错。后来我在工具入口加了类型转换容错性好了很多。第三个坑是忘记处理空结果。检索工具没查到内容时返回空模型拿到空结果后不知道怎么办就卡住了。后来我改成返回“未找到相关内容建议换个关键词试试”模型就能继续了。6. 关于 Agent 开发的一点个人体会写到这里我想分享一个我在实际项目中感受很深的点Agent 的能力上限往往不取决于模型有多强而取决于工具设计得有多好。我见过太多人把精力花在换模型、调参数上但工具本身写得含糊不清结果整个系统表现很差。反过来工具设计得清晰、容错、职责单一即使模型不是最强的整体效果也能接受。另一个体会是可观测性比什么都重要。Agent 的决策过程是个黑盒如果不把每一步的思考、行动、观察都记录下来出问题时根本无从下手。我现在养成的习惯是每次运行都把完整的轨迹存下来方便复盘。这个习惯帮我省了大量调试时间。最后说一个我最近在尝试的方向把 Agent 的执行轨迹作为 RAG 的语料让它在遇到类似任务时能参考之前的成功经验。这个思路还在验证中但初步效果不错。如果你也在做 Agent 开发不妨试试这个方向。
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

◈

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

◐

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

▲

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。