☰
从执行路径看懂 Hermes Agent 架构:事件驱动、工具调用与记忆管理
2026/10/31 8:57:05 网站建设 项目流程

从一次真实任务出发,看懂 Hermes Agent 的架构全貌

接到一个很有意思的活儿:把 Hermes Agent 的项目架构从头到尾拆一遍。这个 Agent 是个纯 AI 智能体框架,核心干的事,是让大模型不只会“聊天”,而是能真正去调用工具、执行动作、完成任务。很多人拿到这样一个框架,第一件事就是看代码、看文档、跑 demo,但真正把它用起来之后,你会发现,制约你效率的往往不是某个具体功能的实现,而是你是否真正理解了它的子系统划分和执行路径。这篇文章我就从架构总览的角度,把 Hermes Agent 剥开,从子系统到执行路径,一次讲透。

先说个结论性的东西:Hermes Agent 不是一个单体的“大模型壳子”,而是由一个事件驱动内核、一个任务规划器、一组可插拔技能模块、一套分层记忆体系和一个工具执行层组成的组合物。它的核心设计思路,是把“理解用户”和“执行动作”彻底解耦——前者由大模型驱动,后者由技能库和工具层接管。这种设计行业内叫“Agent 与 Harness 分离”,说白了就是脑子归脑子,手脚归手脚。

究竟这套架构是怎么运转的?各个子系统之间如何协作?一条用户请求从进来、到拆解、再到执行落地,经过了哪些关卡?接下来我按自己的实操经验,从外到里把整个地图铺开,带你走一遍。

1. 整体架构定位:为什么 Agent 框架要把自己拆成一堆“子系统”

1.1 单体应用时代的教训:不能把“推理”和“执行”焊死在一起

最开始写 Agent 的人,普遍会把大模型 API 调用、工具调用、上下文管理全部塞在一个类里。Demo 阶段确实没问题,用户问“帮我查一下北京的天气”,你调一个函数,返回完事。但一旦需求复杂起来——比如用户要“整理最近一周的会议纪要,提炼待办事项,并自动发邮件给相关人员”——单体会立刻崩溃:prompt 拼接越来越难维护,工具多了以后命名冲突,错误处理散落在各个分支里,记忆和上下文互相污染。

我在实操中见过太多次这种“单体 Agent 后期重构推倒重来”的案例。Hermes Agent 的做法值得借鉴:它把整个系统拆成职责单一的子系统,每个子系统只干一件事,通过定义良好的接口对外暴露能力。这种设计带来的直接好处是,你可以单独替换规划器(比如从默认的 ReAct 换成 Plan-and-Execute),不影响技能库和记忆层;你也可以给 Agent 加一个新的执行插件,完全不需要动内核循环。

1.2 Hermes Agent 的顶层分层:内核、能力、记忆、入口

从最高的视角看,Hermes Agent 分四层:

  • 入口层:负责接收用户输入,无论是 CLI、桌面端对话框还是 API 请求。这一层还承担身份认证和会话管理。
  • 核心层:事件循环、任务规划器、决策模块。这是 Agent 的“大脑中枢”。
  • 能力层:技能库(Skills)、工具注册中心、执行器。这是 Agent 的“手脚”。
  • 记忆层:短期上下文、长期存储、向量检索。这是 Agent 的“海马体”。

我用一句话概括它们的关系:入口层把用户请求翻译成一个内部事件,核心层决定“怎么做”,能力层真正去“做”,做完以后把结果写回记忆层,再由核心层决定下一步。

1.3 “Agent 和 Harness 分离”到底是什么意思

很多刚从 LangChain 之类的框架转过来的同学,会对 Hermes Agent 里的 Harness 概念很陌生。“Harness”直译是“马具”,在 Agent 领域,它指的是承载 Agent 运行的“机身”或“运行时骨架”。简单说,Agent 负责思考(编写计划、调用 LLM),Harness 负责运行(管理循环、分发事件、调度执行器)。

拆开的好处非常实际:Agent 的策略可以不断更换、试验、A/B 测试,而 Harness 的稳定性不因此受影响。反过来,如果某个执行器崩溃了,Harness 能做熔断和重试,Agent 却被蒙在鼓里,不会产生“万念俱灰”式的连锁瘫痪。

2. 核心子系统逐一拆解:五个模块各自承担什么角色

2.1 事件循环内核:一切执行的“心脏”

Hermes Agent 的内核不是传统意义上的“顺序执行函数”,而是一个事件驱动的循环。它维护一个事件队列,支持的事件类型包括:用户消息到达、规划完成、工具执行返回、错误发生、定时器触发等等。每来一个事件,内核就唤醒对应的处理器,处理器再产生新事件放回队列。

这听起来有点抽象,但用场景一讲就明白了:用户说“帮我查一下明天的会议安排,如果和项目评审冲突就调整一下”。入口层把这个请求包装成UserMessageEvent扔进队列。规划器收到这个事件,觉得需要查日历和查评审日程,于是生成ToolInvokeEvent。工具层调用日历 API 返回冲突信息后,产生ToolResultEvent。规划器再次醒来,决定调用另一个工具去调整会议时间。整个过程中,没有任何一个模块是“阻塞等结果”的,全靠事件驱动把流程往前推。

这种设计带来的直接优势是可暂停、可恢复。Agent 在执行过程中如果遇到需要用户确认的决策点(比如发信前确认收件人),它可以挂起当前任务,把状态持久化到记忆层,等用户回复后再恢复执行。这在单体架构里很难实现。

2.2 任务规划与分解引擎:把大目标变成小步骤

这一层是 Hermes Agent 里最“核心技术”的部分。它接收用户意图,输出一个结构化的计划,本质上是:

输入:用户原始诉求 输出:有序的步骤列表,每一步对应一个可执行的技能或工具调用

常用的规划策略有两类。一类是 ReAct 式(边推理边行动,每一步都调用 LLM 判断下一步);另一类是 Plan-and-Execute 式(先一次性生成完整计划,再逐个执行)。Hermes 的规划引擎默认走 Plan-and-Execute,但支持按任务类型动态切换。实际操作中,简单任务(“现在几点”)直接走一步规划;复杂任务(“分析这份销售报表并生成邮件”)走多步规划,规划器还会评估步骤之间的依赖关系。

我建议你重点了解规划器的“成本控制机制”。默认情况下,规划器会限制一次任务的步数上限(比如 20 步),并且每步执行前会预估 token 消耗。这对控制大模型的费用至关重要。我实测过,不加限制地让 Agent 自由决策,一个中复杂度任务的 token 消耗可能膨胀到预期的 4 倍——大部分都浪费在“边想边做”的反复试探上。

2.3 技能库与工具注册中心:扩展能力的“应用商店”

Hermes Agent 把 Agent 能做的每一件事抽象成一个“技能”(Skill)。技能分两个层级:

  • 内置技能:文件读写、HTTP 请求、命令行执行、数据库查询等通用操作。
  • 自定义技能:由用户注册的专属能力,比如“调内部 OA 系统”或“操作某个 SaaS API”。

技能注册中心的本质是一个“路由表”——每个技能声明自己的名称、描述、输入参数 Schema(用 JSON Schema 描述)和调用地址。规划器在选择下一步时,会把用户意图和技能描述做语义匹配,这个匹配过程通常由 LLM 完成,但 Hermes 做了一个非常实用的前置过滤:先通过关键字和向量检索圈定候选技能,再让 LLM 从候选中选,既省 token 又快。

2.4 记忆与上下文管理系统:让 Agent 不会“说完就忘”

记忆层是很多 Agent 框架最容易做烂的地方。简单粗暴的做法是把所有历史消息一股脑塞进 prompt,结果上下文爆炸,模型响应变慢,费用剧增。Hermes 的做法是把记忆分三层:

  • 瞬时记忆(Working Memory):当前任务相关的上下文,只存在于一次任务执行期间。
  • 短期记忆(Short-term Memory):最近几轮对话的关键信息,以结构化摘要的形式保存。
  • 长期记忆(Long-term Memory):用户偏好、历史决策、重要事实,通过向量化存储,按需检索。

这三层记忆与一个“遗忘机制”配合。执行路径每走一步,瞬时记忆里的内容都可能被裁减:无关信息直接丢,关键信息压缩成摘要进入短期记忆。而长期记忆的写入时机,发生在任务成功完成之后——失败的任务只会把“教训”写入短期记忆,不会污染长期记忆。这个细节值得新人在自己的 Agent 里照搬,非常管用。

2.5 工具执行层:把“打算”变成“现实”

工具执行层是子系统和真实世界的最后一道关口。它负责把规划器选中的技能,变成一次实际的命令或 API 调用。执行方式包括本地子进程、HTTP 调用、消息队列投递三种,视技能的类型而定。

这里有一个很多人忽略的关键:工具执行层是有沙箱概念的。部分高风险技能(比如执行任意 shell 命令)会被标记为“需审批”,必须经过用户确认才能执行。执行层还会记录每个工具的调用耗时、成功率、错误信息,这些数据反过来用于规划器在下一次类似任务中做更优的选择。

3. 执行路径全流程追踪:一次任务从输入到落地的八步

3.1 第一阶段:输入解析与会话绑定

用户输入到达入口层,系统先判断该请求属于哪个会话。这一步很关键,因为它决定后续记忆读取的范围:如果你在 Obsidian 插件里唤起 Hermes,它直接关联当前笔记的用户画像和上下文;如果在桌面版对话框里输入,它读取的是默认会话的长期记忆。

输入解析还包含“意图分类”和“参数抽取”。意图分类决定这条请求是走快速通道(比如查询天气)还是复杂通道(需要规划)。参数抽取把“帮我查一下北京和上海明天的天气”拆成两个查询实体。这一步做不好,后续规划器就要多花好几轮试探。

3.2 第二阶段:记忆检索与上下文组装

Hermes 从三层记忆里拼装“当前状态包”,包括:

  • 用户画像(偏好语言、常用地点、历史偏好)
  • 相关长期记忆条目(尝试向量检索,返回 TopK 条)
  • 会话最近摘要
  • 当前任务的工作记忆

这个状态包连同用户的原始输入一起,作为 Prompt 的上下文。拆解下来看,这就是一个“用外部记忆增强 Prompt 质量”的过程。我试过把记忆检索的 TopK 从 3 调到 10,结果模型“记错”的概率反而增加了——因为放进了太多不相关内容干扰决策。建议 TopK 控制在 3-5 之间,宁缺毋滥。

3.3 第三阶段:规划生成与技能匹配

接下来,规划器登场。它拿着组装好的状态包,生成候选计划。计划的核心结构是:

{ "steps": [ { "skill": "weather_query", "parameters": {"city": "北京", "date": "明天"}, "requires_confirmation": false }, { "skill": "weather_query", "parameters": {"city": "上海", "date": "明天"}, "requires_confirmation": false } ], "fallback_strategy": "ask_user_for_clarification" }

生成计划的过程中,规划器先在技能注册中心做一次语义检索,只保留和任务相关的技能描述,交给 LLM 做最终选择。这一前置过滤能省大量 token。我实测在技能库超过 40 个以后,这种“检索-筛选-决策”三步走比直接塞全部技能描述的准确率高很多,且成本低一半以上。

3.4 第四阶段:循环决策与动态调整

计划生成后,进入执行循环。每一次循环,执行引擎取一个步骤,检查是否满足执行前置条件(比如依赖上一步的结果),然后交给工具执行层。这个循环的退出条件有三:

  • 步骤列表全部执行完毕
  • 某个步骤返回致命错误,且无重试计划
  • 用户主动终止

Hermes 的循环决策器不是死板地“按列表走”。每执行完一步,它会拿到真实的执行结果,重新评估剩余步骤是否需要调整。比如规划生成时说“查天气然后决定是否带伞”,查完结果是晴天,第二步就会被优化成“建议不需要带伞”而不是继续调一个“带伞建议工具”。

3.5 第五阶段:工具执行与沙箱控制

工具执行层收到步骤,先做权限校验。如果这个技能被标记为“需审批”,则挂起等待用户确认。审批通过后,执行器按技能注册信息构造实际调用参数,执行并返回结构化结果。

这里有一个值得注意的细节:执行结果的返回格式是统一的,不管底层是 HTTP 返回 JSON,还是命令行输出文本,执行层都会把它们规范化为{status, data, error}结构。这样做的好处是,规划器只需要处理一种结果格式,大大降低了解析失败的几率。

3.6 第六阶段:结果映射与答案生成

所有执行完成后,进入结果映射阶段。这个阶段把工具返回的原始数据,整理成对用户友好的回答。如果执行结果直接满足用户请求,生成最终答复。如果结果不完整,Agent 会判断是否需要追问。

我踩过的一个坑是:在结果映射阶段,LLM 会“自作主张”地润色数据。比如工具返回精确数值 37.2,模型可能在回答里写成“大约 37 度”,导致数值失真。后来我在决策器的 Prompt 里加了硬性约束:回答中涉及数值、日期、名称等信息时,必须严格忠实于工具返回数据,禁止估算。这个问题才算根治。

3.7 第七阶段:记忆写入与上下文清理

任务结束后,Agent 做记忆清理。清理规则大致如下:

  • 任务成功:关键实体、用户偏好、决策路径写入长期记忆
  • 任务失败:失败原因、中间状态写入短期记忆,用于后续调优
  • 瞬时记忆:全部清空

这一步常被初学者忽略,但实际上是 Agent“越用越聪明”的关键。如果你不写记忆,每次任务都从零开始,Agent 永远是个“健忘症”患者。Hermes 的记忆写入是异步的,不会阻塞用户看到最终回复。

3.8 第八阶段:反馈回流与自我修正

最后一步是 Hermes 比较有特色的一环:它会把本次任务的全程执行记录(包括每一步耗时、token 消耗、工具返回结果、出错重试路径)做一次复盘。这个复盘结果不只保存在本地日志里,还会作为后续规划时的“经验参考”。

我在多个 Agent 项目里做过对比:开了反馈回流机制的 Agent,在同一类任务上的成功率,大约经过 20 次迭代后提升了 30% 以上,主要收益来自“避免再次踩同样的错误路径”。

4. 子系统之间的协作与边界:数据流、控制流与故障传导

4.1 数据流:谁产出了什么,谁消费了什么

把八个阶段串起来看,数据流的方向是很清晰的:

  • 入口层产出:用户请求(原始文本 + 会话 ID)
  • 记忆层产出:状态包(用户画像 + 检索记忆 + 摘要)
  • 规划器产出:结构化计划(步骤列表)
  • 执行层产出:工具结果(规范化 JSON)
  • 决策器产出:最终回复(面向用户的文本)

每一层产出的数据,都有明确的消费者。没有“任何一层直接操作另一层的数据存储”这种越界行为。这种边界约束虽然增加了代码量,但极大提升了可维护性——更换记忆存储后端时,规划器和执行层完全无感。

4.2 控制流:事件循环如何把控制权在各个子系统间传递

控制权的传递不是函数调用式的“你调我我调你”,而是通过事件发布/订阅。这样设计的核心收益是“解耦时序依赖”。比如说,执行层调一个外部 API 可能要 3 秒,这 3 秒里规划器并非闲着等待,它可以处理另一个独立子任务(如果存在并行性)。

这种事件驱动方式也有代价:调试难度增加。查一条请求完整的执行路径,你没法单步跟踪函数调用栈,得靠日志追踪事件 ID。我个人在实操时养成的习惯是给每次会话生成一个 Trace ID,贯穿所有日志,并记录每个事件的生命周期(创建、入队、出队、处理完成)。这套日志体系配好以后,排查问题效率能高几倍。

4.3 故障传导:一个工具挂了会怎样

子系统解耦的另一个好处体现在故障隔离上。如果工具执行层调用的外部 API 超时了,它会把超时事件放入队列,规划器收到后可以选择:

  • 重试(若是临时性故障)
  • 换一个等价技能
  • 降级回答(告知用户当前服务不可用)
  • 挂起等待用户指示

我见过不少 Agent 框架在工具层异常时直接把整个任务搞崩,根因是“工具执行”和“任务决策”耦合在一起,一个步骤失败等同于全局失败。Hermes 这种把故障也作为“事件”建模的设计,才是生产级 Agent 该有的气质。

5. 实操经验:配置、调优与踩坑记录

5.1 合理的默认配置清单:拿回去就能用的起点

你说我只想快速跑起来,不想研究源码,那我给你一份可以直接套用的配置思路:

配置项推荐值说明
规划步数上限20防止失控,同时足够覆盖绝大多数任务
记忆检索 TopK3-5太低漏背景,太高添干扰
工具调用超时30 秒覆盖绝大多数 API 场景
需审批技能名单shell_exec, email_send高风险操作一律人工确认
单次任务 token 预算50k超过则主动暂停询问用户
并行子任务数3减少外部 API 限流风险

这套配置是我在多个实际 Agent 项目里迭代出来的,特别适合“通用助理”型场景。如果你的 Agent 只做垂直领域任务,步数上限可以降到 10 以内,速度更快。

5.2 最容易踩的四个坑:我全都替你踩过了

第一个坑:技能描述写得不够清楚。规划器的技能匹配严重依赖技能描述的文字质量。我见过有人把技能描述写成“处理数据”,结果规划器根本无法判断什么时候该调用它。正确做法是详细声明触发场景、输入参数含义、输出内容样例。比如“weather_query:查询指定城市在指定日期的天气情况。输入城市中文名和日期(格式 YYYY-MM-DD)。返回包含温度、天气状况、风力等级的 JSON。”测试下来,描述越具体,技能调用准确率越高。

第二个坑:工具执行结果里塞了太多无关数据。执行层把整个 API 响应原封不动返回,会让结果映射阶段的 LLM 被无关字段干扰。建议执行层做一次字段裁剪,只保留规划器声明需要的输出字段,能显著提升后续决策质量。

第三个坑:记忆写入策略太激进。我最初图省事,所有对话都写入长期记忆,结果长期记忆很快被垃圾填满,向量检索命中一堆和当前任务无关的碎片。后来严格按“只写结论、不写过程;只写事实、不写情绪;只写成功、不写失败”的原则做记忆写入,效果好了很多。

第四个坑:会话上下文里没有时间信息。Agent 规划“明天下午复盘会议”时,如果不知道自己当前所处的日期时间,会出现误判。记得在状态包里固定加上当前时间戳,这个细节几乎每个 Agent 框架都会提示,但每次总有人漏掉。

5.3 排查路径图:任务执行异常时按什么顺序定位

当一条任务执行结果不对,我的排查顺序是:

  1. 先看规划日志:规划器输出的步骤列表是不是合理的?如果规划就不对,问题出在意图解析或记忆检索。
  2. 再看技能匹配:选定步骤里的技能是不是用户真正需要的?如果技能选错,问题出在技能描述质量。
  3. 然后看执行日志:工具调用本身成没成功?返回数据对不对?如果执行失败,问题出在工具对接。
  4. 最后看结果映射:工具结果正确但最终回答不对,问题出在决策器 Prompt。

这套排障顺序能覆盖约九成的异常场景。剩下不到一成的问题,大概率发生在记忆污染和并发冲突上。

写在最后:架构图只是起点,跑通路径才是归宿

我把 Hermes Agent 的这套架构从外到里走了一遍,说实话,真正花时间的地方不在于看懂每个子系统“是干什么的”,而在于理解它们“怎么配合”。很多同学一开始就执着于某个技能模块的细节优化,反而忽略了对执行路径全局的把握。以我这几年的实操体会,架构图是静态的,执行路径才是活的——你只有把一条用户请求从进门到出门的每一步都印在脑子里,才谈得上真正的调优空间。

最后分享一个操作习惯:拿到任意一个 Agent 框架,先在纸上画出它的执行路径,标记每一步的入参、出参、依赖关系、可能失败的点,然后再去写业务代码。这样做看起来多花半小时,但能帮你避开后面数小时的排障折磨。架构阅读,最终是为执行服务的。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询