Hermes Agent 深度解剖:21万星背后的自进化闭环——从三层记忆架构到 GEPA 算法的工程真相
前言
2026年的开源AI Agent赛道热闹非凡。从OpenClaw的跨平台助手,到各类垂直场景的专用Agent,开发者们似乎已经习惯了"每次会话从零开始"这个宿命。但有一个项目从发布第一天起就走了一条完全不同的路——它不仅能帮你干活,还会在每次干活之后反思:这次有什么坑?下次怎么做得更好?然后自动把这个经验写进自己的"操作手册",下次遇到同类问题时直接调用。
这个项目叫 Hermes Agent,来自一家在开源社区久负盛名、但大多数人并不熟悉的团队——Nous Research。截至2026年7月,GitHub Star数已突破21万,是GitHub历史上增长最快的AI Agent项目之一。
很多人听说过它的名号,但真正读懂它工程实现的人并不多。"自进化"听起来像是AGI的前奏,但技术实现往往比产品叙事更克制、更复杂。本文将彻底拆开Hermes Agent的源码和架构设计,从三层记忆架构、Skill自生成引擎、GEPA进化算法、多终端后端设计、到ACP通信协议,手把手带你理解一个真正"会成长"的AI Agent是怎么炼成的。
一、项目全景:它到底是什么?
1.1 一句话定义
Hermes Agent 是一个内置完整学习闭环的开源自进化AI Agent框架。它的核心理念浓缩在项目README的第一句话里:
"The only agent with a built-in learning loop — it creates skills from experience, improves them during use, nudges itself to persist knowledge, searches its own past conversations, and builds a deepening model of who you are across sessions."
翻译过来:它是唯一一个内置完整学习闭环的Agent——它从经验中创建技能、在使用中改进技能、主动提醒自己把重要知识写入持久化记忆、检索自己历史会话中的相关内容,并跨会话对你这个用户建立越来越精确的画像。
这不是一个"包装了一层LLM API的聊天机器人",而是一套完整的Agent Harness(智能体运行时)。它内部维护了68个内置工具、完整的会话存储(SQLite + FTS5全文检索)、上下文压缩、Provider故障切换、密钥池、多终端后端,以及最核心的——自我改进的学习引擎。
1.2 关键数据一览
| 属性 | 详情 |
|---|---|
| 开发者 | Nous Research |
| 许可证 | MIT(完全自由,可商用) |
| 主语言 | Python(占比88.5%)+ TypeScript/TSX(Web UI,占比8.1%) |
| Python版本要求 | ≥ 3.11(硬性要求,不兼容3.10) |
| 总文件数 | ~1717 |
| 测试用例 | ~3000个 |
| 内置工具数量 | 40+ |
| 消息平台支持 | ~10个(Telegram/Discord/Slack/WhatsApp/QQ/飞书等) |
| 内置技能数量 | 288个 |
| 可选技能数量 | 116个 |
| 支持模型Provider | 200+(OpenAI/Anthropic/OpenRouter/GLM/Kimi/MiniMax/DeepSeek/Qwen等) |
| 最低运行配置 | $5 VPS |
| 最高运行配置 | GPU集群、Daytona/Modal Serverless |
1.3 Hermes Agent vs 其他主流Agent框架
市面上类似的工具有不少,但定位差异巨大:
| 特性 | Hermes Agent | OpenClaw | LangChain Agents | AutoGPT |
|---|---|---|---|---|
| 自进化能力 | ✅ 内置闭环 | ❌ 依赖手写Skill | ❌ 无 | ❌ 无 |
| 记忆持久化 | ✅ SQLite FTS5 | ✅ 有(追加模式) | ❌ 无 | ❌ 无 |
| 技能自动生成 | ✅ GEPA算法驱动 | ❌ 纯手动 | ❌ 无 | ❌ 无 |
| 研究/训练支持 | ✅ 内置RL环境 | ❌ 无 | ❌ 无 | ❌ 无 |
| 多终端后端 | ✅ 6种 | ✅ 多种 | ✅ 可扩展 | ❌ 仅本地 |
| Skill格式 | Markdown | Markdown | LangChain格式 | 纯Prompt |
| 代码规模 | ~1700文件 | ~14000文件 | 框架级 | 较小 |
| 学习曲线 | 中等 | 较高 | 高 | 中 |
关键差异:OpenClaw的Skill是手写的——你写多少它会多少,你不写它就不会。Hermes做了一件OpenClaw架构上做不了的事:Agent干完活之后,会自动把踩坑经验提炼成可复用的Skill文件,下次遇到同类问题直接调用。用得越久,能力越强。这不是功能差异,是设计哲学的分野——一个靠人喂,一个自己长。
二、整体架构:一张图看懂全貌
2.1 架构分层全景
Hermes Agent的架构可以划分为五个层次,从上到下依次是:
┌─────────────────────────────────────────────────────────┐
│ Interface Layer(接口层) │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌─────────┐ │
│ │ CLI TUI │ │ Telegram │ │ Discord │ │ Slack │ ... │
│ └──────────┘ └──────────┘ └──────────┘ └─────────┘ │
├─────────────────────────────────────────────────────────┤
│ Agent Core(核心Agent层) │
│ ┌─────────────────┐ │
│ │ AIAgent │ ← run_agent.py,同步对话循环 │
│ │ (主Agent循环) │ │
│ └────────┬────────┘ │
│ │ │
│ ┌────────┴────────────────────────────────────────┐ │
│ │ Tool Registry │ Memory Manager │ Skills System │ │
│ │ Model Meta │ Cron Scheduler │ Context Compressor│ │
│ └─────────────────────────────────────────────────┘ │
├─────────────────────────────────────────────────────────┤
│ Tool Implementations(工具实现层) │
│ terminal │ file │ web │ browser │ code_exec │ delegate│
│ mcp │ vision │ tts │ cron │ delegate │ ... (40+) │
├─────────────────────────────────────────────────────────┤
│ Terminal Backends(终端执行后端) │
│ local │ docker │ ssh │ daytona │ modal │ ... (6种) │
├─────────────────────────────────────────────────────────┤
│ Persistence & Research(持久化与研究层) │
│ ┌─────────────┐ ┌──────────────────────────────────┐ │
│ │ SessionDB │ │ RL Training Environment (Atropos) │ │
│ │ (SQLite │ │ 轨迹记录 │ 批量运行器 │ SWE-bench │ │
│ │ + FTS5) │ └──────────────────────────────────┘ │
│ └─────────────┘ │
└─────────────────────────────────────────────────────────┘
2.2 五个关键架构决策
决策一:同步Agent循环
run_agent.py中的AIAgent是一个完全同步的while循环,没有使用async/await。这个选择看似"保守",实则蕴含深意:
# 来自 run_agent.py 的核心循环(简化版)
while api_call_count < self.max_iterations and self.iteration_budget.remaining > 0:
response = client.chat.completions.create(
model=model,
messages=messages,
tools=tool_schemas
)
if response.tool_calls:
for tool_call in response.tool_calls:
result = handle_function_call(
tool_call.name,
tool_call.args,
task_id
)
messages.append(tool_result_message(result))
api_call_count += 1
else:
return response.content
相比OpenClaw复杂的异步架构,同步设计大大降低了理解和调试的复杂度。对于一个需要快速迭代的开源项目来说,可理解性 > 理论性能。用户实时交互这条链路关心的不是"能跑通",而是"跑不通以后怎么办"——上下文压缩、Provider容错、用户中断、预算耗尽后的Grace Call,这些逻辑在同步模型下更容易推理。
决策二:中心化工具注册
所有工具通过tools/registry.py统一注册和分发。添加一个新工具只需两步:
# 第一步:在 tools/your_tool.py 中定义handler
from tools.registry import registry
@registry.register(
name="your_tool",
description="做什么的",
schema={...}
)
def your_tool_handler(args, context):
# 业务逻辑
return result
# 第二步:在 toolsets.py 中注册
# toolsets.py
TOOLSETS = {
"default": [
# ... 已有工具
"your_tool", # ← 加一行即可
]
}
这种设计让工具体系高度可插拔,新增Provider不需要修改核心代码。
决策三:OpenAI消息格式统一
无论使用哪个LLM Provider(Claude、GPT、DeepSeek等),内部统一使用OpenAI兼容的消息格式:
# 统一的消息格式(OpenAI兼容)
messages = [
{"role": "system", "content": "系统提示词"},
{"role": "user", "content": "用户输入"},
{"role": "assistant", "content": "模型回复", "tool_calls": [...]},
{"role": "tool", "tool_call_id": "...", "content": "工具执行结果"}
]
这使得多Provider适配的复杂度大幅降低,新增一个Provider只需实现一个adapter。
决策四:Profile多实例隔离
通过HERMES_HOME环境变量实现完全隔离的多实例支持。代码中有119+处引用get_hermes_home()确保路径隔离:
# 来自 hermes_state.py
def get_hermes_home() -> Path:
return Path(os.environ.get("HERMES_HOME", "~/.hermes")).expanduser()
这对于多租户场景至关重要——同一台机器上可以运行多个完全隔离的Hermes实例,每个实例有独立的记忆、技能和配置。
决策五:研究导向的模块设计
RL训练环境、轨迹压缩、批量运行器这些模块不是"后来加的",而是从一开始就融入架构设计的核心组件。如果你在做Agent相关的学术研究或模型训练,Hermes Agent几乎是目前最开箱即用的研究平台。
三、三层记忆架构:让Agent"越用越懂你"
Hermes Agent的记忆系统是其区别于所有其他开源Agent的核心。这套系统借鉴了认知科学中经典的记忆三分法理论,将Agent的记忆划分为三个层次:
3.1 第一层:工作记忆(Working Memory)
工作记忆相当于人类的"工作台"——存储当前会话的即时上下文。生命周期与当前会话相同,容量受限于模型的context window大小,作用是维持单次对话的连贯性。
在代码层面,工作记忆由agent/memory_manager.py管理:
# 简化版工作记忆管理逻辑
class MemoryManager:
def __init__(self, session_id: str):
self.session_id = session_id
self.working_memory = [] # 当前会话的消息历史
def add_turn(self, role: str, content: str):
"""添加一轮对话到工作记忆"""
self.working_memory.append({
"role": role,
"content": content,
"timestamp": time.time()
})
def compress_if_needed(self, max_turns: int = 50):
"""当上下文过长时自动压缩"""
if len(self.working_memory) > max_turns:
# 保留首尾关键信息,中间部分做摘要
compressed = self.compress_middle(self.working_memory)
self.working_memory = compressed
当context window快用满时,系统会自动触发上下文压缩——将中间轮次的对话压缩为语义摘要,保留关键决策点和用户偏好信息。这解决了大模型context window有限的问题,让Agent在长会话中依然保持高效。
3.2 第二层:情景记忆(Episodic Memory)
情景记忆相当于人类的"日记本"——记录跨会话的事实、偏好和经历。生命周期为永久保存,存储方式为SQLite + FTS5全文检索,作用是跨会话记住你的项目、偏好和习惯。
# ~/.hermes/ 目录结构
~/.hermes/
├── memories/
│ ├── MEMORY.md # Agent的个人笔记(环境事实、项目约定、工具怪癖)
│ └── USER.md # Agent对用户的认知(偏好、沟通风格、工作习惯)
├── sessions/
│ └── *.db # SQLite会话数据库(带FTS5全文索引)
└── skills/
├── built-in/ # 288个内置技能
└── user/ # 用户创建的技能
这里有一个非常精妙的设计:容量上限故意设得很紧。MEMORY.md限制2200字符,USER.md限制1375字符。这种"容量有限就迫使Agent挑重要的记"的机制,比OpenClaw的纯追加模式(用几个月就膨胀成几万行的怪兽文件)要健康得多。
举一个实际场景:
第1天:
你:"我的项目用的是Next.js 14 + TypeScript + TailwindCSS"
Hermes Agent:[自动写入USER.md] 用户偏好: Next.js 14, TypeScript, TailwindCSS
第30天:
你:"帮我加一个新页面"
Hermes Agent:[自动检索USER.md] 检测到用户项目技术栈 → 直接用Next.js 14创建页面组件,样式用TailwindCSS
这就是跨会话记忆的实际价值——你不需要重复解释自己的技术栈和环境,Agent会自己记住。
3.3 第三层:程序记忆(Procedural Memory)
程序记忆相当于人类的"肌肉记忆"——将反复执行的复杂操作固化为自动化技能。这是Hermes Agent最独特的设计,也是其"自进化"能力的基础。
当Agent完成一个复杂任务后,它会评估:这次操作是否值得沉淀为可复用技能?
# 自生成技能的简化逻辑(来自源码概念)
def evaluate_and_create_skill(self, task: Task, result: Result):
# 1. 评估:这个任务是否有复用的价值?
if self.is_reusable(task, result):
# 2. 提取:把这次的经验提炼成结构化的Skill文件
skill_content = self.extract_skill(task, result)
# 3. 写入:生成Markdown格式的Skill文件
skill_path = self.skills_dir / f"{skill.name}.md"
with open(skill_path, "w") as f:
f.write(skill_content)
# 4. 注册:让系统知道这个新技能
self.skill_registry.register(skill)
# 5. 优化:如果已有同名技能,比较并选择更好的版本
self.gepa_optimize(skill.name)
生成的Skill文件是Markdown格式,人类可读可编辑:
---
name: deploy-nextjs-to-vercel
description: 一键将Next.js项目部署到Vercel平台
trigger_keywords: ["部署", "vercel", "发布", "deploy"]
---
# 部署Next.js到Vercel
## 适用场景
当用户要求将Next.js项目部署上线时使用此技能。
## 操作步骤
### 1. 检查项目环境
\`\`\`bash
cd /path/to/project
# 确认是Next.js项目
ls package.json | grep next
\`\`\`
### 2. 安装Vercel CLI(如未安装)
\`\`\`bash
npm i -g vercel
\`\`\`
### 3. 执行部署
\`\`\`bash
vercel --yes
\`\`\`
### 4. 生产环境部署
\`\`\`bash
vercel --prod
\`\`\`
## 注意事项
- 首次部署需要登录Vercel账号
- 环境变量需要在Vercel控制台配置
- 部署完成后会自动生成生产URL
这种"任务完成 → 经验沉淀 → 技能固化 → 持续优化"的闭环,让Hermes Agent真正实现了"越用越聪明"。
3.4 Honcho用户建模系统
除了三层记忆架构,Hermes Agent还集成了Honcho——一个跨会话的用户画像系统。Honcho通过分析用户的历史对话,自动构建用户的偏好模型:
# Honcho用户建模的核心逻辑
class HonchoUserModeling:
def analyze_conversation(self, messages: list) -> UserProfile:
profile = UserProfile()
# 分析编程语言偏好
profile.languages = self.extract_language_preferences(messages)
# 分析工具偏好
profile.tools = self.extract_tool_preferences(messages)
# 分析沟通风格
profile.communication_style = self.analyze_style(messages)
# 分析工作习惯
profile.work_habits = self.extract_work_habits(messages)
return profile
def build_context(self, profile: UserProfile) -> str:
# 将用户画像注入到系统提示词中
return f"""
用户画像:
- 常用语言:{', '.join(profile.languages)}
- 偏好工具:{', '.join(profile.tools)}
- 沟通风格:{profile.communication_style}
- 工作习惯:{', '.join(profile.work_habits)}
"""
这样,每次新的会话开始时,Agent就已经知道你是谁、你喜欢用什么工具、你习惯怎么沟通,从而提供更个性化的服务。
四、Skill自进化引擎:从经验中长出能力
4.1 技能系统的基本结构
Hermes Agent的技能系统兼容agentskills.io开放标准,所有技能都是Markdown格式,人类可读、可编辑、可版本控制。内置288个技能,覆盖了文件操作、代码编写、终端命令、网页搜索、数据处理等常见场景。
技能文件的完整结构:
---
name: skill-name # 技能唯一标识
description: 简短描述 # 用于Agent检索
trigger_keywords: # 触发关键词
- "关键词1"
- "关键词2"
version: "1.0.0" # 版本号
author: "auto-generated" # auto-generated表示自动生成
created_at: "2026-07-25" # 创建时间
---
# 技能标题
## 描述
详细的技能描述,说明适用场景和使用方法。
## 前置条件
使用此技能前需要满足的条件。
## 执行步骤
### 步骤1:XXX
\`\`\`bash
command_or_code
\`\`\`
### 步骤2:XXX
...
## 注意事项
- 注意事项1
- 注意事项2
## 示例
\`\`\`example
输入: xxx
输出: xxx
\`\`\`
4.2 闭环学习循环的五个阶段
Hermes Agent的学习闭环分为五个阶段,形成一个完整的自进化循环:
┌─────────────────────────────────────────────────────────┐
│ │
│ 阶段1:执行任务 │
│ Agent接收用户请求,调用工具链完成任务 │
│ ↓ │
│ 阶段2:观察结果 │
│ 记录执行轨迹、耗时、错误信息、中间状态 │
│ ↓ │
│ 阶段3:提取经验 │
│ 分析执行过程中的关键决策点、踩过的坑、有效的策略 │
│ ↓ │
│ 阶段4:创建/改进技能 │
│ 生成或更新Skill文件,提炼可复用的操作流程 │
│ ↓ │
│ 阶段5:持久化知识 │
│ 将重要事实写入MEMORY.md/USER.md,跨会话保留 │
│ │
│ ↑ │
│ └────────────── 下一轮任务使用改进后的技能 ←──────┘
└─────────────────────────────────────────────────────────┘
4.3 Nudge Engine:定时触发的"反思闹钟"
光有闭环还不够——Agent可能会"忘记"反思。Hermes Agent内置了Nudge Engine,定时提醒Agent反思和沉淀:
# Nudge Engine的核心逻辑
class NudgeEngine:
def __init__(self):
self.nudge_interval = timedelta(hours=2) # 每2小时提醒一次
self.last_nudge = None
def should_nudge(self) -> bool:
"""判断是否应该触发Nudge"""
if self.last_nudge is None:
return True
return datetime.now() - self.last_nudge >= self.nudge_interval
def generate_nudge(self, agent_state: AgentState) -> str:
"""生成Nudge提示"""
return f"""
[Nudge] 你已经运行了一段时间。请检查:
1. 有什么重要的环境信息值得写入MEMORY.md吗?
当前工作目录:{agent_state.cwd}
检测到的技术栈:{agent_state.detected_stack}
2. 有什么用户偏好值得写入USER.md吗?
用户最近请求:{agent_state.recent_requests[-3:]}
3. 有什么操作流程值得固化为Skill吗?
最近执行的复杂任务:{agent_state.complex_tasks[-1]}
"""
4.4 GEPA算法:进化式的技能优化
当同一个Skill被多次调用后,Hermes Agent会启动GEPA(Generative Evolutionary Performance Assessment)算法来优化它。这套算法是Hermes区别于所有其他Agent框架的核心技术创新。
GEPA的工作原理:
# GEPA算法的核心流程(简化版)
class GEPA:
def optimize_skill(self, skill_name: str):
# 1. 读取当前Skill文件
current_skill = self.read_skill(skill_name)
# 2. 从历史会话中采样或合成评估数据集
eval_dataset = self.build_evaluation_dataset(skill_name)
# 3. 生成多个候选变体
candidates = []
for i in range(5): # 生成5个变体
variant = self.mutate_skill(current_skill)
candidates.append(variant)
# 4. 评估每个候选变体
results = []
for candidate in candidates:
score = self.evaluate(candidate, eval_dataset)
results.append((candidate, score))
# 5. Pareto前沿选择:不选全局最优,而是选每个评估样本上的最优
pareto_optimal = self.pareto_selection(results)
# 6. 如果有改进,创建PR供人工审查
if pareto_optimal.score > current_skill.score:
self.create_pull_request(skill_name, pareto_optimal)
def mutate_skill(self, skill: Skill) -> Skill:
"""对Skill进行变异操作"""
mutations = [
self.simplify_steps, # 简化步骤
self.add_error_handling, # 增加错误处理
self.optimize_command_order, # 优化命令顺序
self.add_alternatives, # 增加替代方案
self.reduce_token_usage, # 减少token使用
]
mutation = random.choice(mutations)
return mutation(skill)
Pareto前沿选择是GEPA的核心创新点。传统的优化算法会选择"平均分最高"的变体,但GEPA认为:一个Skill的价值不在于平均表现,而在于它是否在某些场景下表现最好。只要一个候选在任意一个评估样本上表现最好,就会被保留到下一代。
def pareto_selection(self, candidates: list) -> list:
"""
Pareto前沿选择算法
一个解不被另一个解在所有维度上支配,则该解在Pareto前沿上
"""
pareto_front = []
for candidate, score in candidates:
is_dominated = False
for other, other_score in candidates:
if other is candidate:
continue
# 如果other在所有维度上都不比candidate差,且至少一个维度更好
if self.dominates(other_score, score):
is_dominated = True
break
if not is_dominated:
pareto_front.append((candidate, score))
return pareto_front
4.5 DSPy + GEPA集成
Hermes Agent的技能优化引擎底层集成了DSPy框架,用于自动优化提示词和工具描述:
| 优化目标 | 引擎 | 许可证 | 集成方式 |
|---|---|---|---|
| 技能文件 | GEPA | MIT | 原生集成 |
| 系统提示词 | DSPy | MIT | 原生集成 |
| 工具描述 | DSPy | MIT | 原生集成 |
| 指令模板 | GEPA | MIT | 原生集成 |
这种"进化式优化"的方法论,让技能系统不是静态的,而是活的——随着使用次数的增加,每个技能都在持续改进。
五、多终端后端:一张命令跨所有环境执行
5.1 六种执行后端
Hermes Agent支持六种不同的终端执行后端,让同一套Agent代码可以运行在任何环境中:
| 后端 | 说明 | 适用场景 |
|---|---|---|
local | 直接在本地执行命令 | 本地开发、快速测试 |
docker | 在Docker容器中执行 | 隔离环境、生产部署 |
ssh | 通过SSH连接到远程服务器执行 | 远程服务器、云计算 |
daytona | Daytona云开发环境 | 云端开发、团队协作 |
modal | Modal Serverless平台 | 弹性计算、按需扩展 |
inference | 推理专用后端 | 模型服务、AI计算 |
这个设计解决了Agent部署的一个核心痛点:同一套Agent代码,在本地调试时用local后端,生产部署时切换到docker后端,完全无需修改业务逻辑。
5.2 后端抽象层设计
所有后端都实现了统一的抽象接口:
from abc import ABC, abstractmethod
class TerminalBackend(ABC):
@abstractmethod
def execute(self, command: str, cwd: str = None) -> ExecutionResult:
"""执行命令并返回结果"""
pass
@abstractmethod
def upload_file(self, local_path: str, remote_path: str) -> bool:
"""上传文件"""
pass
@abstractmethod
def download_file(self, remote_path: str, local_path: str) -> bool:
"""下载文件"""
pass
@abstractmethod
def get_env_info(self) -> EnvInfo:
"""获取环境信息(操作系统、Python版本等)"""
pass
# 具体实现
class DockerBackend(TerminalBackend):
def execute(self, command: str, cwd: str = None) -> ExecutionResult:
# Docker特有的实现
container = self.get_container()
result = container.exec_run(
cmd=f"bash -c 'cd {cwd} && {command}'"
)
return ExecutionResult(
stdout=result.output.decode(),
stderr=result.stderr.decode(),
exit_code=result.exit_code
)
5.3 工具链的跨环境适配
不同后端环境下,同一个工具可能需要不同的实现。Hermes Agent通过工具适配器模式解决这一问题:
# 工具的跨环境适配
class FileTool(AgentTool):
def __init__(self, backend: TerminalBackend):
self.backend = backend
def execute(self, operation: str, path: str, content: str = None):
if self.backend.type == "docker":
# Docker环境下的文件操作需要特殊处理
return self._docker_file_op(operation, path, content)
elif self.backend.type == "ssh":
# SSH环境下通过SFTP操作文件
return self._ssh_file_op(operation, path, content)
else:
# 本地环境直接操作
return self._local_file_op(operation, path, content)
六、消息网关:从终端到全平台的覆盖
6.1 ACP协议:Agent Communication Protocol
Hermes Agent通过**ACP(Agent Communication Protocol)**连接各种消息平台。ACP是一种专为AI Agent设计的通信协议,支持:
- 多轮对话管理:支持上下文连续性
- 工具调用传递:将Agent的工具调用结果回传给用户
- 多租户隔离:每个用户/群组独立会话
- 消息格式标准化:统一Telegram/Discord/Slack/WhatsApp的消息格式
# ACP适配器的核心接口
class ACPAdapter(ABC):
@abstractmethod
def send_message(self, chat_id: str, message: ACPMessage) -> str:
"""发送消息到指定渠道"""
pass
@abstractmethod
def on_message(self, raw_message: Any) -> ACPMessage:
"""将原始消息转换为ACPMessage格式"""
pass
@abstractmethod
def build_reply_context(self, message: ACPMessage) -> dict:
"""构建回复上下文"""
pass
# 支持的平台
PLATFORMS = {
"telegram": TelegramACPAdapter,
"discord": DiscordACPAdapter,
"slack": SlackACPAdapter,
"whatsapp": WhatsAppACPAdapter,
"qq": QQACPAdapter,
"feishu": FeishuACPAdapter,
}
6.2 Gateway架构
消息网关采用插件化架构,每个平台是一个独立的插件:
gateway/
├── __init__.py
├── base.py # 网关基类
├── message_router.py # 消息路由器
└── platforms/
├── telegram/
│ ├── bot.py # Telegram Bot实现
│ ├── handlers.py # 消息处理器
│ └── config.py # 配置
├── discord/
│ └── ...
├── slack/
│ └── ...
└── ...
新增一个消息平台只需实现对应的Adapter即可,核心逻辑无需修改。
6.3 ACP Registry服务发现
Hermes Agent还支持ACP Registry——一个服务发现机制,让多个Agent实例之间可以互相通信和协作:
# ACP Registry的简化实现
class ACPRegistry:
def __init__(self):
self.services = {}
def register(self, agent_id: str, endpoint: str, capabilities: list):
"""注册一个Agent服务"""
self.services[agent_id] = {
"endpoint": endpoint,
"capabilities": capabilities,
"registered_at": time.time()
}
def discover(self, capability: str) -> list:
"""发现提供特定能力的Agent"""
return [
agent for agent in self.services.values()
if capability in agent["capabilities"]
]
def delegate_task(self, task: Task, target_capability: str) -> str:
"""将任务委托给具备特定能力的Agent"""
candidates = self.discover(target_capability)
if not candidates:
raise NoAgentFoundError(f"No agent with capability: {target_capability}")
# 选择最合适的Agent(负载最低、响应最快)
target = self.select_best(candidates)
return self.forward_task(task, target["endpoint"])
这使得多Agent协作成为可能——一个Agent发现自己的记忆里有相关信息,可以自动委托给另一个专门处理该领域的Agent。
七、代码实战:构建你的第一个自进化Skill
7.1 场景设定
让我们通过一个具体场景来理解Skill的生成和使用过程。假设用户向Hermes Agent提出以下请求:
"帮我把这个Python脚本改成并发版本,要求用asyncio实现。"
7.2 Agent执行过程
# 第一步:理解任务
user_request = "帮我把这个Python脚本改成并发版本,要求用asyncio实现"
task_analysis = agent.analyze_task(user_request)
# 输出:Task(type="code_rewrite", lang="python", pattern="concurrent", framework="asyncio")
# 第二步:检查是否有相关Skill
existing_skill = agent.skill_registry.find("python-asyncio-concurrent")
if existing_skill:
# 直接复用已有Skill
steps = existing_skill.execute(original_code)
else:
# 执行任务(这里省略具体实现)
steps = agent.execute_code_rewrite(original_code, "asyncio")
# 第三步:执行工具调用
for step in steps:
result = agent.tools.execute(step)
agent.memory.add_turn("tool", result)
if result.status == "error":
agent.handle_error(result)
# 第四步:任务完成,评估是否需要生成Skill
if agent.should_create_skill(task_analysis, result):
# 生成新的Skill文件
new_skill = agent.generate_skill_from_experience(
task=task_analysis,
execution_trace=agent.get_trace(),
result=result
)
agent.skill_registry.register(new_skill)
print(f"✅ 已生成新技能:{new_skill.name}")
7.3 生成的Skill文件示例
---
name: python-async-concurrent-rewrite
description: 将同步Python代码改写为asyncio并发版本
trigger_keywords:
- "asyncio"
- "并发"
- "concurrent"
- "异步改写"
version: "1.0.0"
author: auto-generated
created_at: "2026-07-25"
---
# Python asyncio 并发改写技能
## 适用场景
当用户要求将同步Python代码改写为异步并发版本时使用。
## 改写规则
### 规则1:同步函数 → 异步函数
\`\`\`python
# 改写前
def fetch_data(url):
response = requests.get(url)
return response.json()
# 改写后
async def fetch_data(url: str, session: aiohttp.ClientSession) -> dict:
async with session.get(url) as response:
return await response.json()
\`\`\`
### 规则2:for循环 → asyncio.gather
\`\`\`python
# 改写前
results = []
for url in urls:
results.append(fetch_data(url))
# 改写后
async def fetch_all(urls: list) -> list:
async with aiohttp.ClientSession() as session:
tasks = [fetch_data(url, session) for url in urls]
return await asyncio.gather(*tasks)
\`\`\`
### 规则3:time.sleep → asyncio.sleep
\`\`\`python
# 改写前
import time
time.sleep(1)
# 改写后
import asyncio
await asyncio.sleep(1)
\`\`\`
### 规则4:requests → aiohttp
\`\`\`python
# 改写前
import requests
response = requests.get(url)
# 改写后
import aiohttp
async with aiohttp.ClientSession() as session:
async with session.get(url) as response:
return await response.json()
\`\`\`
## 完整改写模板
\`\`\`python
import asyncio
import aiohttp
async def async_main(urls: list):
async with aiohttp.ClientSession() as session:
tasks = [fetch_data(url, session) for url in urls]
return await asyncio.gather(*tasks)
if __name__ == "__main__":
urls = ["https://api.example.com/data/1", ...]
results = asyncio.run(async_main(urls))
\`\`\`
## 注意事项
- 异步函数内部不能直接调用同步阻塞代码(如time.sleep)
- 需要安装aiohttp:`pip install aiohttp`
- 并发数过多可能导致请求被限流,需要添加信号量控制并发数
7.4 在实际场景中使用
下次用户再说"帮我把data_fetcher.py改成并发"时,Agent会:
- 检索Skill Registry,找到
python-async-concurrent-rewrite - 读取Skill文件,加载到工作记忆
- 按照Skill定义的改写规则处理原始代码
- 输出改写后的完整代码
整个过程无需人工介入,Agent自动完成了经验积累和能力提升。
八、部署实践:从$5 VPS到GPU集群
8.1 一键安装
Hermes Agent的安装非常简单,一条命令搞定所有依赖:
curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bash
source ~/.bashrc # 或 source ~/.zshrc
hermes --version
安装脚本会自动检测操作系统(Linux/macOS/WSL2/Termux),并安装Python、Node.js、ripgrep等所有依赖。
8.2 不同场景的部署方案
场景1:本地开发(推荐配置)
# 使用local后端,本地执行所有命令
hermes setup
# 选择 "1. Quick setup"
# 配置API Key(支持OpenAI/Anthropic/OpenRouter等多种Provider)
hermes start
# 启动Web面板和CLI界面
场景2:$5 VPS生产部署
# 使用docker后端,隔离运行环境
hermes config set backend docker
hermes config set docker_image nousresearch/hermes-agent:latest
# 配置开机自启
sudo systemctl enable hermes-agent
# 启动服务
hermes start
场景3:GPU集群训练
# 使用ssh后端连接GPU服务器
hermes config set backend ssh
hermes config set ssh_host gpu-cluster.example.com
hermes config set ssh_user deploy
# 启动RL训练
hermes train --model hermes-3-llama-3-8b --episodes 10000
8.3 环境变量配置
# ~/.hermes/.env
HERMES_HOME=~/.hermes # 数据目录
LLM_PROVIDER=openrouter # 模型提供商
OPENROUTER_API_KEY=sk-or-... # API Key
DEFAULT_MODEL=anthropic/claude-3-5-sonnet # 默认模型
BACKEND=docker # 执行后端
LOG_LEVEL=INFO # 日志级别
MAX_ITERATIONS=100 # 最大迭代次数
SESSION_TIMEOUT=3600 # 会话超时(秒)
九、与OpenClaw的横向对比
作为2026年最火的两款开源Agent框架,Hermes Agent和OpenClaw经常被拿来比较。下面从五个维度进行深度对比:
9.1 记忆系统对比
| 维度 | Hermes Agent | OpenClaw |
|---|---|---|
| 存储方式 | SQLite FTS5 + 纯文本 | 纯文本(MEMORY.md) |
| 容量控制 | 硬性上限(2200/1375字符) | 无限制(追加模式) |
| 跨会话检索 | FTS5全文搜索 | 线性扫描 |
| 用户建模 | Honcho自动分析 | 手动维护 |
| 记忆质量 | 自我策展(Agent决定记什么) | 被动记录 |
结论:Hermes Agent的记忆系统更智能,OpenClaw的记忆系统更简单。
9.2 安全架构对比
| 维度 | Hermes Agent | OpenClaw |
|---|---|---|
| 危险命令检测 | 47条规则自动拦截 | 配置化 |
| 执行后端隔离 | docker/ssh多种后端 | 主要本地 |
| 多租户隔离 | HERMES_HOME环境隔离 | Workspace隔离 |
9.3 技能插件对比
| 维度 | Hermes Agent | OpenClaw |
|---|---|---|
| Skill生成 | 自动+GEPA优化 | 纯手动 |
| Skill格式 | Markdown(人类可读) | Markdown |
| 技能市场 | Skills Hub在线市场 | Skill文件本地管理 |
| 技能数量 | 288+116可选 | 依赖用户创建 |
9.4 选择建议
- 选择Hermes Agent:如果你想要一个"越用越聪明"的Agent,重视自动化的经验积累,或者在做Agent相关的学术研究
- 选择OpenClaw:如果你需要更丰富的多渠道支持(语音、Canvas等),或者需要一个开箱即用的多模态助手
十、总结与展望
10.1 Hermes Agent的核心价值
Hermes Agent之所以能在不到半年内积累21万Star,本质上是因为它解决了一个根本问题:传统Agent是"无状态的",每次会话从零开始;Hermes Agent是"有记忆的",每次会话都在积累经验。
这种"自我进化"的设计哲学,让AI Agent从"工具"进化成了"数字同事"。你不是在"使用"一个AI,而是在"培养"一个越来越懂你的AI伙伴。
10.2 技术亮点总结
- 三层记忆架构:工作记忆、情景记忆、程序记忆,模拟人类认知科学的记忆模型
- GEPA进化算法:用进化计算的思想持续优化Skill,让能力随使用次数增长
- 六种终端后端:统一的抽象接口,让同一套代码运行在任何环境
- ACP通信协议:标准化的多平台消息网关,支持多Agent协作
- 研究就绪:内置RL训练环境、轨迹记录、批量评估器,是Agent研究的最佳平台
10.3 未来展望
从目前的发展趋势来看,Hermes Agent可能会在以下几个方向持续演进:
- 多Agent协作:ACP Registry的完善,支持多个Hermes实例之间的任务分工
- 更强大的推理能力:集成更多推理模型,提升复杂任务的规划能力
- 技能市场的繁荣:随着用户贡献的Skill越来越多,Skills Hub可能成为AI Agent的"GitHub"
- 端侧部署:针对移动端和嵌入式设备的轻量化优化
参考资料
- Hermes Agent GitHub仓库
- Hermes Agent官方文档
- Nous Research官网
- GEPA算法论文(博客解析)
- Hermes Agent架构深度解析
- 深度拆解 HermesAgent系列
本文基于Hermes Agent v0.10.0源码分析,项目持续迭代中,具体实现可能随版本更新而变化。如有疏漏,欢迎指正。