首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >AI Agent 决策架构演进:从 ReAct 到 MCP、Hermes,把底层机制讲透

AI Agent 决策架构演进:从 ReAct 到 MCP、Hermes,把底层机制讲透

原创
作者头像
老周聊架构
发布于 2026-09-24 21:48:46
发布于 2026-09-24 21:48:46
1100
举报

如果你在 2022 年之前问一个大模型"帮我查一下上海明天的天气,然后订一张去那里的机票",它会非常自信地编出一段看起来合理但实际全是幻觉的回答。不是因为它笨,而是因为它的整个世界观里只有"生成下一个 token",没有任何机制让它去和外部世界发生交互、验证自己的假设、或者纠正自己的错误。

这件事背后的核心矛盾是:语言模型擅长"生成看似合理的文本",但解决真实问题需要"获取真实信息、基于反馈决策、在错误中迭代"。从静态生成到动态决策,中间隔着一整条架构演进的鸿沟。过去三年业界填这条沟的过程,就是 Agent 决策架构的演进史。

Agent 这个方向要解决的问题,本质上就是给大模型装上"手"和"脑回路"。这只手能调用工具拿回真实数据,这条脑回路能在拿到反馈后重新思考。过去三年,业界在这个方向上走出了一条非常清晰的演进路径:从 ReAct 的推理行动交织,到 Reflexion 的自我反思闭环,到 Tool Calling 的接口标准化,到 MCP 的上下文协议统一,再到 Hermes 这种原生 function-calling 智能体。

这篇文章我想把这条路线讲透,不是罗列名词,而是回答一个更本质的问题:每一代架构到底解决了前一代解决不了的什么痛点,为什么演进是必然的而不是噱头。

第一代:ReAct,让推理和行动在同一个循环里交织

ReAct 的全称是 Reasoning and Acting,出自 2022 年 Yao 等人的论文。它的核心思想极其朴素但影响深远:不要把"思考"和"行动"分开,而是让 LLM 在同一个生成序列里交替输出 Thought(思考)、Action(行动)和 Observation(观察)。

具体机制是这样的。模型拿到一个任务后,先输出一段 Thought,用自然语言描述自己当前的理解、已经知道什么、还缺什么。然后它输出一个 Action,格式通常是 Action: 工具名[参数]。这个 Action 被外部执行器拦截,真正去调用对应工具(比如搜索、计算器、数据库查询),拿到结果后,系统把结果包装成 Observation 重新拼回上下文。模型看到 Observation 后,基于新的事实再输出下一个 Thought,如此循环,直到它认为自己掌握了足够信息,输出 Final Answer。

ReAct 最妙的地方在于,它几乎没有改模型本身,纯粹靠 prompt 工程就实现了"推理指导行动,行动反哺推理"的闭环。模型在 Thought 里把任务拆解成子目标,在 Action 里选择工具,在 Observation 里验证假设。比如任务"谁在打败了阿尔法狗的公司的创始人出生地出生",模型会先 Thought:我需要先找打败阿尔法狗的公司,再找它的创始人,再找创始人的出生地。然后 Action 去搜索,Observation 回来,再继续。

值得强调的是,ReAct 的 Thought 不只是给外面看的"思维链",它是真正的规划载体。在 HotpotQA 这样的多跳推理数据集上,有 Thought 引导的模型明显比纯 Action 或者纯思维链的表现更好,因为 Thought 强迫模型在行动前先声明自己的中间假设,而这些假设一旦被 Observation 证伪,模型就能在下一轮 Thought 里显式地纠正方向,而不是在错误的路径上越走越远。

但 ReAct 有一个结构性缺陷:它的 Action 是用自由文本生成的,靠正则或启发式去解析 Action: search[xxx] 这种字符串。解析一失败,整个循环就断了。而且它每次都是单步串行,模型想一次查两个东西就得分两轮。还有更深的隐患:ReAct 的错误是一次性的,模型在一个 Episode 里犯了错,下一轮它并没有"记住"自己上次为什么错,只是被动地拿到新的 Observation 再碰运气。一旦陷入错误循环,模型可能反复调用同一个失败的工具十几轮,token 烧光了问题还没解决。这就逼出了第二代。

第二代:Reflexion,把失败变成可写入的长期记忆

Reflexion 由 Shinn 等人于 2023 年提出,它要补上的是 ReAct 缺失的那块:自我反思和记忆。ReAct 是"试一次,看结果",Reflexion 是"试一次,复盘,把复盘写进记忆,再试"。

它的架构多了一个关键角色:verbal memory。每一轮 Trial 结束后,模型不只看环境返回的成功或失败信号,还要生成一段自我反思(self-reflection)。这段反思是用自然语言写的,内容大致是"我刚才的做法有什么问题,下次应该换什么策略"。比如它在代码生成任务上跑挂了测试用例,反思会说"我不该用那个已经废弃的 API,而且我对边界条件的处理漏了空指针"。

这段反思随后被写入一个 memory 库,不是向量数据库那种模糊检索,而是作为显式的文本片段持久保留。下一轮 Trial 开始时,这些反思文本会被注入上下文,模型在规划时就能直接参考"我之前在这里踩过坑"。这个设计本质上是在模拟人类的学习方式:你做错一道题,不是简单地再试一次,而是停下来想"我为什么错",然后把那个教训记住。

Reflexion 论文里其实区分了几种记忆:短期记忆是单轮 Episode 内的轨迹,长期记忆是跨 Episode 积累的反思,还有一类是环境自身的状态。它的反思生成也分层次,有的是对具体错误的纠正式("这里应该用 BFS 而不是 DFS"),有的则是对策略的元级反思("我应该先收集所有约束再动手")。这种分层让模型既能修具体 bug,也能调整整体方法论。

Reflexion 的闭环是:Trial(执行行动)拿到环境反馈(成功/失败 + 具体错误信息)后触发 Reflection(生成自然语言反思),反思写入 Memory,Memory 参与下一轮规划,如此迭代直到任务通过或达到最大步数。实验表明在决策、推理、编程多个 benchmark 上,加入反思闭环后成功率显著提升,尤其是那些需要多步纠错的复杂任务。在 ALFWorld 这类需要长程规划的具身任务里,Reflexion 把成功率从 ReAct 基线的水平往上拉了十几个百分点。

不过 Reflexion 也不是银弹。它的记忆是文本追加式的,轮次多了上下文会膨胀,而且反思质量完全依赖模型自身的元认知能力。模型要是反思错了,错误记忆反而会把后续决策带偏。另外,它和 ReAct 一样,底层还是有自由文本解析工具调用的脆弱性。要真正解决工具调用的可靠性,得从接口层动手,这就是第三代。

第三代:Tool Calling 标准化,用 JSON Schema 锁死接口

前两段讲的 ReAct 和 Reflexion,工具调用都建立在"模型输出一段约定格式的文本,外部正则解析"之上。这种方式在工程上极脆:模型偶尔多写一个换行、参数格式稍微飘一下、或者输出中英混杂,解析就挂了。而且不同模型用不同的文本约定,换模型就得重写解析器。

Tool Calling 标准化要做的事,是把"调用工具"这件事从自由文本提升为一等公民。核心机制是 JSON Schema 约束的函数调用。开发者在请求模型时,附带一份工具定义,每个工具用 JSON Schema 精确描述:函数名、参数名、参数类型、是否必填、取值范围。模型在需要调用工具时,不再输出自然语言字符串,而是输出一段结构化的 JSON,里面是函数名和符合 Schema 的参数值。调用方拿到这段 JSON 之后,可以直接用类型安全的反序列化去执行,几乎不可能解析失败。

这里有几个关键升级点。其一是参数强约束,JSON Schema 让模型知道每个参数该填什么类型、什么格式,模型胡编的概率大幅降低,因为如果输出不符合 Schema,API 层会直接拒绝并要求重填。模型不再需要"猜"参数的形状,它会按照训练时见过的 Schema 结构老老实实填空。其二是并行调用,标准化之后的接口可以支持一次返回多个 tool call,模型能在同一个回复里说"同时去查天气、查汇率、查日历",执行器并行打出去,整体延迟从 O(n) 降到接近 O(1)。这在实时性敏感的场景(比如一个 Agent 同时监控多个数据源)里价值巨大。其三是可组合性,工具定义变成了一份声明式契约,模型提供商、框架、开发者之间有了统一语言,不再各自一套文本格式。

还有一个工程上特别重要的点:可观测性。自由文本解析时代,你很难判断模型"想调什么工具、传了什么参数",因为那是一段自然语言。标准化之后,每一次调用都是结构化日志,你可以直接把 tool call 落表,做回放、做审计、做成本分析。这对生产系统是刚需。

和自由文本解析对比,标准化的代价是模型需要针对 function calling 做对齐训练,推理时要走专门的 decode 路径。但收益是质的:可靠性、可观测性、可组合性全部上一个台阶。OpenAI 在 2023 年中的 function calling、以及后续各家的 tool use,走的都是这条路线。今天你几乎看不到还有人在生产环境用正则解析 Action: 字符串了,这就是标准化胜利的最直接证据。

第四代:MCP,把工具的接入从私有插件变成开放协议

Tool Calling 解决了"怎么调用一个工具"的标准化,但还有一个更上层的痛点没解决:每个应用、每个框架、每个模型厂商都在自己定义工具怎么连、资源怎么传、上下文怎么组织。你要给 Agent 接一个数据库,得给 LangChain 写一套 Tool,给某个闭源产品写一套 Plugin,换一家又得重写。工具的供给方被锁死在消费方的私有格式里,这是巨大的重复建设。

MCP(Model Context Protocol,模型上下文协议)由 Anthropic 在 2024 年底提出,思路类比 LSP(语言服务器协议)或者 USB 接口:定义一套标准化的通信协议,让任何 MCP Client(宿主应用)都能连任何 MCP Server(工具/数据源提供方),不用关心对方内部怎么实现。

MCP 的架构分三层。最上面是 Host/Client 层,运行在 Agent 应用里,负责发起请求、管理连接。中间是 Server 层,每个 Server 封装一类能力,比如文件系统访问、数据库查询、第三方 API 集成。最底层的 Transport 层负责实际传输,定义了两种标准传输方式:stdio(本地进程间通信,Server 跑在本地子进程里)和 HTTP with SSE(远程通信,Server 可以部署在远端)。

这两种传输方式的选择是有讲究的。stdio 模式下,Server 作为本地子进程由 Host 拉起,所有数据都在本机内存里流转,天然适合访问本地文件、本地数据库这类敏感资源,数据不出本机。远程模式下,Server 是独立部署的网络服务,Host 通过 HTTP 连上去,适合那种需要集中托管、多租户共享的工具能力(比如一个公司内部的统一检索服务)。一个设计良好的 MCP 生态里,本地和远程 Server 可以混用,Host 不关心背后是哪一类,只管按协议发 JSON-RPC 消息。

协议定义了三个核心原语。Tools 是模型可以主动调用的函数,对应"行动能力",每个 tool 同样用 JSON Schema 描述输入输出。Resources 是模型可以读取的上下文数据,比如一个文件、一段数据库结果、一份文档,对应的是"感知能力",由应用决定何时注入。Prompts 是预定义的提示模板,可以被用户或模型触发,用来固化一些常见工作流。

MCP 最大的价值在于解耦。本地 Server 通过 stdio 跑,天然安全,数据不出本机;远程 Server 通过 HTTP 暴露,可以被多个 Host 共享。一旦生态形成,工具提供方只要实现一个 MCP Server,就能被所有兼容 MCP 的 Agent 消费,不用再为每个框架单独适配。这比各厂各自的私有 plugin 体系好太多了:私有 plugin 是围墙花园,MCP 是开放总线。对架构师来说,这意味着你设计 Agent 系统时,工具层从"和具体框架深度绑定的代码"变成了"可插拔的标准协议端点"。

第五代:Hermes Agent,让原生 function calling 成为模型的出厂能力

前面几代要么是 prompt 技巧(ReAct、Reflexion),要么是协议层抽象(MCP),要么是大厂的 API 特性(Tool Calling)。Hermes 系列工作(来自 Nous Research)走的是另一条更底层、更像"从模型训练阶段就解决问题"的路:通过指令微调,让开源模型原生具备可靠的函数调用与多轮工具对话能力。

Hermes 的核心做法是 prompt 模板化的 function calling。它在训练数据构建阶段,就把工具定义、工具调用、工具返回值、以及模型基于返回值继续推理的多轮对话,按照一套统一的模板结构化成训练样本。模型不是去"猜测"某个私有格式,而是在预训练和微调阶段就见过成千上万个规范的函数调用对话范式,从而学会在推理时原生输出可被解析的调用 JSON。

和 ReAct 那种"在 prompt 里用文字写 Action: xxx"不同,Hermes 的调用是模型语言能力的一部分,输出的是纯粹结构化、可被代码直接反序列化的 JSON,没有正则解析的负担。和单纯依赖闭源 API 的 Tool Calling 不同,Hermes 把这套能力开放给了开源社区,让开发者可以在自己的模型上微调出同样的能力。

Hermes 特别强的一点是多轮工具对话。真实业务里,一次任务往往要在"调用工具拿数据、基于数据思考、再调用另一个工具"之间往返好几轮。Hermes 的训练数据显式覆盖了这种多轮结构,模型学会了在每一轮里判断:我现在该直接回答,还是该再调一个工具,还是该把之前几轮的结果综合起来。它把 ReAct 的"推理行动交织"从 prompt 技巧内化成了模型的本能。

这里值得一提的是训练数据的构建哲学。Hermes 不是简单拿现成的 API 调用日志来训练,而是用强大的教师模型(比如 GPT-4 级别)去生成大量规范化的"工具定义-调用-返回-推理"三元组对话,覆盖单轮、多轮、并行、错误处理等多种形态,再拿去微调开源基座。这种"用强模型教弱模型怎么用工具"的蒸馏思路,让一个 7B、13B 的小模型也能获得接近闭源大模型的工具使用可靠性。对想在本地私有化部署 Agent 的团队来说,这条路线意味着你不必依赖大厂的闭源 API 就能拥有可靠的 function calling 能力。

我的看法是,Hermes 这条路线代表了一个重要趋势:Agent 能力正在从"在通用模型外面套一层工程脚手架"向"模型本身就懂怎么用工具"演进。工程脚手架永远有它的位置(比如 MCP 管连接、Reflexion 管记忆),但底层的调用可靠性、多轮规划能力,最终应该长在模型权重里。这就像编译器从手写汇编演化到高级语言自带优化,基座越强,上层越薄。

演进的本质:从技巧堆叠到协议统一,再到能力内化

把五代串起来看,你会发现一条非常清晰的主线。ReAct 证明了"推理和行动可以交织",但它用的是文本解析这种脆弱方式。Reflexion 证明了"失败可以变成记忆",但记忆是追加文本,且依赖前代调用方式。Tool Calling 标准化把调用从文本提升到结构化接口,解决了可靠性。MCP 把工具的接入从各厂私有格式统一成开放协议,解决了生态解耦。Hermes 把可靠的调用和多轮规划做进模型训练,让能力从外部脚手架内化进基座。

每一代都在补前一代的结构性短板,而不是凭空造概念。如果你今天要设计一个生产级 Agent 系统,我的建议是分层看待:基座模型选一个 function calling 对齐得好的(无论开源 Hermes 系还是闭源 API),工具接入层用 MCP 做解耦,复杂任务里叠加 Reflexion 式的反思记忆做纠偏,至于 ReAct 的循环骨架,它已经溶解在每一代的实现里,变成了基础设施而非feature。

技术的演进从来不是线性叠加,而是每一层把下一步的假设垫实。理解这一点,你才不会在下一个"Agent 新范式"出来时盲目追新,而是能判断它到底在补哪块地基。

落到工程实践,我的建议是别迷信任何单一范式。ReAct 的循环骨架值得保留,但要用结构化调用替换文本解析;Reflexion 的反思记忆在长时间任务上收益明显,但对简单任务反而是负担;Tool Calling 和 MCP 已经是事实标准,新项目没有理由不用;Hermes 这类原生能力越强,你上层的工程代码就越能简化。选型的本质是看你卡在哪一层,然后只补那一层,不要为了用而用。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

目录
  • 第一代:ReAct,让推理和行动在同一个循环里交织
  • 第二代:Reflexion,把失败变成可写入的长期记忆
  • 第三代:Tool Calling 标准化,用 JSON Schema 锁死接口
  • 第四代:MCP,把工具的接入从私有插件变成开放协议
  • 第五代:Hermes Agent,让原生 function calling 成为模型的出厂能力
  • 演进的本质:从技巧堆叠到协议统一,再到能力内化
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档