2.2. 六大子系统构成 Agent 操作系统的内核
六大子系统构成 Agent 操作系统的内核
如果你曾用 SSH 登录过一台 Linux 服务器,你接触的是 Shell;如果你曾双击打开过一个 App,你接触的是 GUI。但无论是哪种交互界面,支撑它们运行的,都是操作系统内核里那些永远在后台静默运转的子系统——进程调度、内存管理、文件系统、网络栈。它们从不直接露面,却决定了整个系统能做什么、有多快、会不会崩溃。
2026 年 2 月,Nous Research 在 GitHub 上发布了 Hermes Agent。表面上看,这只是一个能用自然语言聊天、能帮你写代码的 AI 助手。但当你真正走进它的架构内部,你会发现一个惊人的事实:Hermes Agent 不是一个“模型 + 循环”的简单脚本,而是一个完整的 Agent 操作系统。 它的内核由六大子系统构成,每一个都对应着传统操作系统中一个久经考验的设计理念。
上一章我们拆解了三层骨架如何将 Agent 的调用方式与执行逻辑解耦。但那只是“外壳”。这一章,我们打开外壳,走进内核。你会看到一条消息总线如何成为 Agent 的神经中枢,一套提示构建器如何像虚拟内存管理器一样精打细算地使用上下文窗口,以及一个名为 Nudge Loop 的自进化调控器如何让 Agent 在没有用户指令的情况下,自己学会复盘。
核心结论前置:Agent 操作系统的六大子系统不是六个独立模块的堆砌,而是一条环环相扣的流水线。消息流入总线,提示在装配线上被拼接,工具在调度器中被执行,记忆在持久化引擎中被沉淀,技能在管理器中被提炼,而 Nudge Loop 像一个永不休息的守护进程,周期性地检查这一切是否运转正常。
| 子系统 | 操作系统类比 | 核心职责 | 一句话理解 |
|---|---|---|---|
| Message Bus | 内核消息队列 | 统一路由所有内部事件与外部输入 | Agent 的神经中枢 |
| Prompt Builder | 虚拟内存管理 | 上下文的拼接、裁剪与缓存复用 | 在有限窗口内装下无限上下文 |
| Tool Dispatch | 系统调用接口 | 工具注册、参数验证、结果回送 | 让 Agent 的手能伸到外部世界 |
| Memory Subsystem | 文件系统 | 持久化存储用户偏好与项目状态 | 让 Agent 记住你是谁 |
| Skill Manager | 包管理器 | 技能的定义、加载、执行与升级 | 让 Agent 的能力可进化 |
| Nudge Loop | Cron 守护进程 | 周期性自检信号的产生与投递 | Agent 的自我复盘本能 |
读完这张表,你已经理解了六大子系统的全貌。接下来,我们逐一深入每个子系统的内部,看看它们到底是怎么工作的——以及,为什么这些设计会出现在一个“聊天机器人”的代码库里。
Message Bus:Agent 的神经中枢
在 Hermes Agent 的代码中,你找不到一个名为 main_loop() 的函数。这让很多初次阅读源码的开发者感到困惑:如果没有一个主循环在轮询输入,Agent 怎么知道该什么时候“思考”?
答案是:Agent 不需要轮询,因为它有一条消息总线。
消息总线(Message Bus)采用了发布/订阅模式。任何外部输入——Telegram 消息、Discord 指令、CLI 输入、定时任务触发——到达后,都会被封装成统一的消息结构,投递到总线上。内部事件也一样:工具执行完毕、子 Agent 返回结果、Nudge 信号触发,都走同一条总线。
这种设计的精妙之处在于解耦。Gateway 层(三层骨架中的第一层)只需要把不同平台的输入翻译成标准消息格式,剩下的路由、优先级、并发控制,全部交给消息总线处理。这意味着:
- 新增一个平台(比如 WhatsApp)不需要修改任何内核代码。 只需要写一个新的 Gateway Adapter,把 WhatsApp 消息翻译成标准格式,然后丢到总线上。
- 内部事件的优先级可以动态调整。 比如,当一个子 Agent 返回了紧急结果,这条消息可以被标记为高优先级,插队到当前处理队列的前端。
- 所有消息天然可追溯。 因为每条消息都经过总线,调试时只需要在总线上挂一个监听器,就能看到 Agent “看到”了什么、“想到”了什么。
从当前调研资料看,Hermes 的消息总线还支持持久化消息队列——当 Agent 重启时,未处理的消息不会丢失。这是一个典型的“企业级消息中间件”设计被搬进了 Agent 架构。
Prompt Builder:上下文装配线
如果说消息总线解决了“什么时候思考”,那么 Prompt Builder 解决的就是“思考时能看到什么”。
LLM 的上下文窗口是有限的。虽然最新的模型已经支持 128K 甚至 1M token 的上下文,但成本与延迟仍然随着上下文增长而飙升。Prompt Builder 的任务是:在每一次 LLM 调用前,动态装配出一个最优的上下文,既包含足够的信息让 Agent 做出正确决策,又不浪费任何一个 token。
它内部有三条装配流水线:
| 流水线 | 作用 | 典型组件 |
|---|---|---|
| 模板拼接 | 注入系统角色、工具描述、项目规则 | System Prompt 模板 + 运行时变量填充 |
| 上下文裁剪 | 当历史对话超过阈值时自动压缩或截断 | 滑动窗口 + 摘要生成器 |
| 缓存复用 | 避免相同前缀被重复编码 | Prefix Caching 命中检查 |
一个典型的 Prompt 装配过程是这样的:模板拼接器先从 Memory Subsystem 读取 MEMORY.md 和 USER.md,注入系统提示词;然后上下文裁剪器检查对话历史,如果超过 8000 token,触发自动摘要;最后,缓存复用器检查本次的 System Prompt 是否与上次相同,如果命中缓存,直接复用 KV Cache,省下一次完整的 Prefill。
这套机制解释了为什么你在 CLI 中看到的“上下文自压缩”不是魔法——它是 Prompt Builder 在后台自动执行的。从工程角度看,这非常类似于操作系统中的虚拟内存管理:物理内存(上下文窗口)是有限的,但通过分页、交换和缓存,进程(Agent)可以“看到”一个近乎无限的逻辑内存空间。
Tool Dispatch:统一工具接口
Agent 的本质是“思考 + 行动”。思考由 LLM 完成,行动则由工具调用实现。Tool Dispatch 子系统就是 Agent 的“系统调用接口”——就像 Linux 的 syscall 指令,为上层应用(Agent 的推理逻辑)提供一组标准化的、与底层实现无关的能力。
它的工作流程分为三段:
- 工具注册:每个工具(比如读取文件、执行 Shell 命令、搜索网页)在启动时向 Tool Registry 注册自己的名称、描述、参数 Schema 和回调函数。
- 参数验证:当 LLM 决定调用某个工具时,Tool Dispatch 会先用 JSON Schema 验证参数格式,再用自定义的 Sanitizer 检查参数内容(比如防止路径注入)。
- 结果回送:工具执行完毕后,结果被封装成标准消息,通过 Message Bus 送回 LLM 的上下文中,触发下一轮推理。
这里有一个容易被忽略的设计细节:工具调用的结果是异步回送的。 也就是说,LLM 发出工具调用指令后,不会阻塞等待结果——它继续处理消息总线上的其他事件,工具结果到达后自动插入上下文。这种异步设计让 Hermes Agent 可以同时发起多个工具调用(比如并行搜索三个网页),而不是一个接一个地串行执行。
# 工具注册示例(简化版)
@tool_registry.register(
name="read_file",
description="读取指定路径的文件内容",
parameters={
"path": {"type": "string", "description": "文件路径"}
}
)
async def read_file(path: str) -> str:
# Sanitizer 会在调用前自动检查路径
with open(path, "r") as f:
return f.read()
这种标准化设计还带来了一个额外好处:社区贡献新工具极其简单。你只需要遵循接口规范写一个函数,加上 Schema 描述和提示词片段,Agent 就能自动学会使用它。Hermes 社区已经贡献了超过 200 个这样的工具,覆盖从天气查询到 PDF 解析的各种场景。
Memory Subsystem:状态持久化引擎
很多人以为 Agent 的“记忆”就是对话历史。这是误解。对话历史只是在本次会话中保持上下文,一旦会话结束或上下文被裁剪,它就消失了。真正的记忆,是跨会话持久化的——你今天告诉 Agent 你用的是 Python 3.11,三天后它还能记住。
Hermes 的 Memory Subsystem 由两个核心文件驱动:
- MEMORY.md:项目级记忆。记录当前项目的技术栈、目录结构、关键决策。每个项目目录下可以有一个独立的 MEMORY.md。
- USER.md:用户级记忆。记录用户的偏好、习惯、常用工具。存储在 Agent 的全局配置目录中。
但这两个文件只是“存储介质”。Memory Subsystem 真正的能力在于它的后端连接器(Memory Backend)。从当前调研资料看,Hermes 支持多种记忆后端:
| 后端类型 | 适用场景 | 持久化能力 |
|---|---|---|
| 本地文件 | 单机使用,零配置 | 文件系统 |
| SQLite | 结构化查询,中等规模 | 本地数据库 |
| Qdrant/Chroma | 向量检索,语义记忆 | 向量数据库 |
| 自建服务 | 企业级部署 | 任意数据库 |
这种插件化设计让 Memory Subsystem 可以适配从个人笔记本到企业数据中心的任何环境。当 Agent 需要回忆某条信息时,它会先查本地 SQLite(精确匹配),再查向量数据库(语义相似),最后才去读 MEMORY.md 文件(全文扫描)——这是一个典型的分级存储架构。
值得注意的是,记忆是可以被“污染”的——这是社区中最常见的踩坑之一。如果某次对话中你的描述有歧义,Agent 可能提炼出错误的记忆并在后续会话中持续应用。解决方法也很直接:手动编辑 MEMORY.md 或 USER.md 文件,它们是纯 Markdown,你可以直接修改。
Skill Manager:可进化的能力单元
如果 Tool 是 Agent 的“手”,那么 Skill 就是 Agent 的“肌肉记忆”。Tool 是外部能力的调用接口(比如调用 Shell 命令),Skill 则是经过提炼的、可复用的能力单元(比如“自动部署一个 Docker 容器”的完整流程)。
Hermes 的 Skill Manager 引入了一个极其创新的概念:Agent 可以自己创建 Skill。
当 Agent 成功解决了一个难题——比如终于排除了某个环境配置问题——它会在内部总结出一个 Skill 文档。这个文档不是简单的日志,而是一个结构化的操作手册,包含:
- 触发条件:什么时候应该激活这个 Skill
- 前置检查:执行前需要验证什么
- 执行步骤:具体操作的序列
- 回滚方案:如果失败怎么办
- 标签与描述:便于后续搜索和复用
Skill 文件遵循 agentskills.io 开放标准,这意味着它们可以在不同 Agent 之间共享。实际上,Hermes 的 Skill Manager 已经形成了一个小型生态:社区贡献了大量 Skill,覆盖从“安装 CUDA”到“配置 Nginx 反向代理”的各种场景。
# Skill: fix_python_env
触发条件: 用户报告 Python 导入错误或版本冲突
前置检查:
1. 检查 pip list 输出
2. 确认虚拟环境是否激活
执行步骤:
1. 如果虚拟环境未激活,提醒用户激活
2. 如果包版本冲突,执行 pip install --upgrade
3. 如果问题持续,建议创建新的虚拟环境
回滚: 记录修改前的 pip list 快照
Skill Manager 的升级流程同样精妙:当 Agent 在一个相似但略有不同的场景下执行 Skill 失败后,它会尝试调整步骤并记录差异。如果调整后的方案连续成功三次,Skill Manager 会自动更新原始 Skill 文件——这就是“可进化”三个字的工程实现。
Nudge Loop:自进化的调控器
六个子系统中,Nudge Loop 是最容易被忽视、也最关键的一个。它解决了一个根本问题:如果用户不主动要求复盘,Agent 怎么知道自己该成长?
传统 Agent 的“学习”完全依赖用户触发。用户说“你错了”,Agent 纠正;用户说“记住这个”,Agent 记录。但 Hermes 的设计团队意识到,这种被动学习模式有一个巨大缺陷:用户不会主动告诉 Agent 它做错了什么——因为用户可能根本不知道 Agent 内部发生了什么。
于是,Nudge Loop 诞生了。
Nudge Loop 是一个周期性的自检信号发生器。每经过一定轮次的对话(默认 10 轮),系统自动产生一条内部 Nudge 消息,投递到 Message Bus 上。这条消息不是用户发出的,而是系统对自己说:“嘿,你已经连续工作了一段时间,检查一下,有没有什么可以总结的?”
Nudge 消息到达后,Agent 会执行一次轻量级的自我复盘:
- 回顾最近的对话:有没有重复犯过同样的错误?
- 检查工具调用效率:有没有更短的执行路径?
- 评估记忆使用情况:有没有可以提炼成 Skill 的操作模式?
- 生成改进提案:如果有发现,输出一个结构化的总结,等待用户确认或自动应用。
这个机制的本质,是把“复盘”从用户要主动触发的外部行为,变成了 Agent 自己的内部本能。它就像操作系统的 Cron 守护进程——在后台静默执行,从不打扰用户,但保证了整个系统的持续进化。
六大子系统的协作全景
现在,让我们把所有子系统串联起来,看一次完整的执行流程:
- 你在 Telegram 上发送:“帮我分析这个 CSV 文件里的销售数据。”
- Gateway 将 Telegram 消息翻译为标准格式,投递到 Message Bus。
- Message Bus 唤醒 Agent 推理循环。
- Prompt Builder 从 Memory Subsystem 读取 MEMORY.md(你之前说过你在做季度复盘),从 Skill Manager 读取相关 Skill(数据分析 Skill),拼接出完整 Prompt。
- LLM 决定调用 CSV 解析工具,通过 Tool Dispatch 发起调用。
- Tool Dispatch 验证参数,执行工具,将结果异步回送到 Message Bus。
- 经过几轮工具调用和推理后,Agent 返回分析报告。
- 10 轮对话后,Nudge Loop 触发自检,Agent 发现自己对 CSV 分析的流程可以提炼成一个新 Skill。
- Skill Manager 创建新 Skill,Memory Subsystem 更新相关性标签。
六个子系统,形成了一条完美的闭环流水线。
在下一章《Agent Runtime 的执行循环采用了增强型 ReAct 模式》中,我们会跟踪这个流水线中最核心的一环:思考→决策→行动→观察→再思考的全过程。 你会看到,上面说到的“LLM 决定调用 CSV 解析工具”这一瞬间,在 Runtime 层面是如何被分解成一次精密的推理循环的。
Hermes Agent 系统设计与工程落地
关于 LearnKu