从一次真实任务出发看懂 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 负责思考编写计划、调用 LLMHarness 负责运行管理循环、分发事件、调度执行器。拆开的好处非常实际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 排查路径图任务执行异常时按什么顺序定位当一条任务执行结果不对我的排查顺序是先看规划日志规划器输出的步骤列表是不是合理的如果规划就不对问题出在意图解析或记忆检索。再看技能匹配选定步骤里的技能是不是用户真正需要的如果技能选错问题出在技能描述质量。然后看执行日志工具调用本身成没成功返回数据对不对如果执行失败问题出在工具对接。最后看结果映射工具结果正确但最终回答不对问题出在决策器 Prompt。这套排障顺序能覆盖约九成的异常场景。剩下不到一成的问题大概率发生在记忆污染和并发冲突上。写在最后架构图只是起点跑通路径才是归宿我把 Hermes Agent 的这套架构从外到里走了一遍说实话真正花时间的地方不在于看懂每个子系统“是干什么的”而在于理解它们“怎么配合”。很多同学一开始就执着于某个技能模块的细节优化反而忽略了对执行路径全局的把握。以我这几年的实操体会架构图是静态的执行路径才是活的——你只有把一条用户请求从进门到出门的每一步都印在脑子里才谈得上真正的调优空间。最后分享一个操作习惯拿到任意一个 Agent 框架先在纸上画出它的执行路径标记每一步的入参、出参、依赖关系、可能失败的点然后再去写业务代码。这样做看起来多花半小时但能帮你避开后面数小时的排障折磨。架构阅读最终是为执行服务的。