Hermes Agent 深度实战:当 AI 学会「自我进化」——从四层记忆架构到生产级部署的完全指南(2026)
作者按:Hermes Agent 是 2026 年 AI Agent 领域最具颠覆性的开源项目。它不是另一个「调用 API 的壳」,而是一个真正具备自我进化能力的数字员工。本文将深入剖析其四层记忆架构、技能自动生成机制、多平台网关设计,并通过完整的 Python 代码示例,带你从零到生产级部署。
目录
- 为什么需要「会进化」的 AI Agent?
- Hermes Agent 是什么?核心定位解析
- 四层自进化闭环架构深度拆解
- 四层记忆系统:从「记不住」到「越用越懂你」
- 技能引擎:让 AI 从「每次从零开始」到「积累可复用经验」
- 多平台网关:一个 Agent 打通所有沟通渠道
- 生产级部署实战(Python 全栈)
- 与 OpenClaw/Claude Code 的架构对比
- 性能优化与踩坑指南
- 未来展望:自进化 Agent 的下一个里程碑
1. 为什么需要「会进化」的 AI Agent?
1.1 传统 AI 助手的「失忆症」困境
如果你用过 ChatGPT、Claude 或其他 AI 助手,一定遇到过这样的场景:
场景一:重复解释背景
你:「帮我优化这段代码的性能。」
AI:「好的,请问是什么项目的代码?用的什么框架?」
你:「就是昨天让你写的那个电商爬虫啊!」
AI:「抱歉,我无法记住昨天的对话…」
场景二:同类错误反复犯
你第 N 次:「怎么又忘了在 SQL 查询里加索引?上周 production
AI:「抱歉,我会注意的。」
(下次依然犯同样的错误)
场景三:无法积累领域知识
你:「根据我们公司的代码规范,这个函数命名应该用驼峰…」
AI:「好的。」
(新会话开始,一切归零)
这些问题的根源在于:传统 AI 助手是无状态的(stateless)。每次对话都是一次「冷启动」,模型不保留任何跨会话的记忆,更不用说从经验中学习了。
1.2 现有方案的局限性
社区尝试过多种「补丁式」方案:
| 方案 | 原理 | 缺陷 |
|---|---|---|
| 超长 Context Window | 把历史对话全塞进 Prompt | 成本爆炸、噪音增多、无法真正「理解」历史 |
| RAG(检索增强) | 向量数据库存储知识库 | 只是「检索」而非「学习」,无法沉淀经验 |
| Fine-tuning | 用历史数据微调模型 | 成本高、周期长、无法实时进化 |
| 规则引擎 + Prompt 模板 | 硬编码常见场景的处理逻辑 | 维护成本爆炸、无法覆盖长尾场景 |
核心矛盾:这些方案都是在「堆外部存储」,而非让 AI 真正具备自主学习能力。
1.3 Hermes Agent 的破局思路
Hermes Agent 的核心创新在于:把「学习」本身变成 Agent 主循环的一部分。
传统 Agent:用户输入 → 推理 → 工具调用 → 返回结果 → 结束(遗忘)
Hermes Agent:用户输入 → 推理 → 工具调用 → 返回结果 → 反思 → 写入技能/记忆 → 下次更强
关键差异:
- 传统 Agent 的「记忆」是被动存储(你让它记住什么,它就存什么)
- Hermes Agent 的「记忆」是主动策展(它会自己判断什么值得记住、什么应该忘掉)
2. Hermes Agent 是什么?核心定位解析
2.1 官方定义
Hermes Agent 是由 Nous Research(知名开源 AI 实验室,以 Hermes 系列 LLM 闻名)于 2026 年 2 月发布的开源、自托管、具备自我进化能力的 AI 智能体框架。
核心定位(官方原话翻译):
"The first open-source autonomous agent with a built-in learning loop. Hermes doesn't just chat — it remembers, it learns, it evolves."
2.2 三大核心特性
特性一:自我进化闭环(Self-Evolution Loop)
这是 Hermes 最颠覆性的创新。完成任务后,Agent 会自动反思:
- 这次任务中,哪些步骤是通用的?
- 能否把这些步骤提炼成可复用的「技能」(Skill)?
- 下次遇到类似任务,能否直接调用这个技能?
示例:
# 你让 Hermes 帮你写一个爬虫抓取电商网站价格
# 任务完成后,Hermes 自动生成技能文件:
# skills/ecommerce_crawler.md
"""
## Skill: E-commerce Price Crawler
### Trigger Conditions:
- User mentions "crawl", "scrape", "price", "ecommerce"
### Steps:
1. Check robots.txt compliance
2. Use Playwright for JS-rendered pages
3. Implement rate limiting (2 req/s)
4. Store in SQLite with upsert
### Lessons Learned:
- Always add User-Agent header (learned from 403 error on 2026-03-15)
- Some sites block headless browsers → use stealth mode
"""
下次你说「帮我抓取书店的价格」,Hermes 会自动加载这个技能,而不需要从零开始摸索。
特性二:四层记忆架构(Four-Layer Memory Stack)
Hermes 的记忆系统不是简单的「键值存储」,而是分层设计的认知模型:
| 层级 | 名称 | 存储内容 | 生命周期 | 技术实现 |
|---|---|---|---|---|
| L1 | 会话记忆 | 当前对话的上下文 | 会话结束即清除 | LLM Context Window + 动态摘要 |
| L2 | 持久记忆 | 跨会话的关键事实、用户偏好 | 永久(除非主动删除) | MEMORY.md + USER.md(字符硬限制) |
| L3 | 技能记忆 | 从任务中提炼的可复用技能 | 永久,持续进化 | skills/*.md + FTS5 全文检索 |
| L4 | 用户建模 | 用户的思维模式、沟通习惯 | 永久,隐私敏感 | Honcho / Mem0 / Holographic(可插拔) |
设计哲学:
- 有界(Bounded):每层都有严格的容量上限(防止记忆膨胀)
- 策展式(Curated):Agent 主动决定「记住什么」,而非无脑存储
- 缓存友好(Cache-friendly):通过快照冻结机制,避免频繁刷新系统提示词缓存
特性三:多平台网关(Multi-Platform Gateway)
Hermes 不是「某个平台的一个机器人」,而是一个 Agent 实例,多个触达渠道:
你的 Hermes Agent 实例
├── Telegram Bot(随时随地交互)
├── Discord Bot(社区协作)
├── 企业微信/钉钉/飞书(国内办公场景)
├── CLI(本地开发)
├── VSCode/IDE 插件(编码助手)
└── Web UI(自定义前端)
所有渠道共享同一套记忆和技能 —— 你在 Telegram 上教它的东西,在 VSCode 里它依然记得。
2.3 技术栈概览
| 组件 | 技术选型 | 说明 |
|---|---|---|
| 核心框架 | Python 3.10+ | 轻量级,易扩展 |
| LLM 支持 | 20+ 提供商 | OpenAI/Anthropic/DeepSeek/智谱 GLM/本地 Ollama 等 |
| 记忆存储 | SQLite + FTS5 | 全文检索 + WAL 模式高性能写入 |
| 技能格式 | Markdown | 人类可读 + LLM 可解析 |
| 网关协议 | ACP(Agent Communication Protocol) | 与 IDE/编辑器标准对接 |
| 调度器 | 内置 Cron | 支持定时任务、心跳检测 |
| 部署方式 | 自托管(Docker/ pip) | 数据完全私有 |
3. 四层自进化闭环架构深度拆解
Hermes Agent 的架构设计可以用一句话概括:以 Agent 执行循环为「中枢神经」,围绕它构建记忆、技能、网关、调度四大子系统。
让我们自顶向下,逐层拆解。
3.1 第一层:推理核心层(Inference Core Layer)
职责:负责与 LLM 交互,完成「理解输入 → 推理 → 生成响应」的核心流程。
3.1.1 多模型支持与降级机制
Hermes 内置 Model Router,支持 20+ LLM 提供商,并且实现了自动降级(Fallbacks):
# hermes/core/model_router.py(伪代码)
class ModelRouter:
def __init__(self):
self.providers = {
"primary": "anthropic/claude-3-5-sonnet-20241022",
"fallbacks": [
"openai/gpt-4-turbo",
"deepseek/deepseek-chat",
"local/ollama/llama3.3-70b"
]
}
async def complete(self, messages, tools):
for attempt, model in enumerate([self.primary] + self.fallbacks):
try:
return await self.call_llm(model, messages, tools)
except RateLimitError:
logger.warning(f"Model {model} rate limited, trying fallback...")
continue
except APIError as e:
if attempt == len(self.fallbacks):
raise
continue
生产级建议:
- 主模型用 Claude 3.5 Sonnet(推理质量最高)
- 第一降级用 GPT-4 Turbo(能力强,偶尔降价)
- 第二降级用 DeepSeek(成本低,中文友好)
- 最终降级用本地 Ollama(完全离线,保护隐私)
3.1.2 工具调用(Tool Calling)优化
Hermes 的工具调用不是简单的「JSON Schema 映射」,而是做了工具结果的智能缓存:
# 工具调用优化示例
TOOL_CACHE_TTL = 300 # 5 分钟内相同的工具调用直接返回缓存
async def execute_tool(tool_name, tool_input):
cache_key = f"{tool_name}:{hash(tool_input)}"
if cache_key in tool_cache and not is_expired(cache_key):
return tool_cache[cache_key]
result = await actually_execute(tool_name, tool_input)
tool_cache[cache_key] = (result, time.now() + TOOL_CACHE_TTL)
return result
实战场景:
- 你问「今天天气怎么样?」,Hermes 调用天气 API
- 30 秒后你又问「需不需要带伞?」,Hermes 不会重复调用 API,而是直接从缓存读取
3.2 第二层:多级记忆层(Multi-Level Memory Layer)
这是 Hermes 的「灵魂」所在。让我们深入四层记忆的每一个细节。
3.2.1 L1:会话记忆(Session Memory)
技术实现:LLM 原生的 Context Window + 动态摘要策略
核心挑战:当对话长度接近 Context Window 上限时,如何避免「遗忘早期重要内容」?
Hermes 的解决方案是 Context Compressor(上下文压缩器):
# hermes/memory/context_compressor.py(核心逻辑)
class ContextCompressor:
def __init__(self, max_tokens=128000, reserve_tokens=10000):
self.max_tokens = max_tokens
self.reserve_tokens = reserve_tokens # 保留给新消息的空间
async def compress_if_needed(self, conversation_history):
current_tokens = count_tokens(conversation_history)
if current_tokens < self.max_tokens - self.reserve_tokens:
return conversation_history # 不需要压缩
# 五阶段压缩策略
# Stage 1: 裁剪工具输出(保留前 500 token + 后 500 token)
compressed = self.truncate_tool_outputs(conversation_history)
# Stage 2: 保护头部(System Prompt + 前 3 轮对话不压缩)
compressed = self.protect_header(compressed)
# Stage 3: 尾部保留(最近 10 轮对话完整保留)
compressed = self.preserve_recent(compressed, num_turns=10)
# Stage 4: LLM 摘要(对中间部分生成摘要)
compressed = await self.llm_summarize_middle(compressed)
# Stage 5: 注入记忆提示(告诉 LLM「这是压缩后的历史」)
compressed = self.inject_compression_notice(compressed)
return compressed
生产级踩坑:
- 不要压缩过度:保留最近 10 轮完整对话,否则 LLM 会「忘记刚才说了什么」
- 工具输出是大头:一次浏览器自动化可能返回 50KB 的 HTML,必须裁剪
- 摘要质量取决于模型:用 Claude 3.5 Sonnet 做摘要,不要用 GPT-3.5
3.2.2 L2:持久记忆(Persistent Memory)
技术实现:MEMORY.md + USER.md + SQLite FTS5 全文检索
文件结构:
# MEMORY.md(Agent 视角的记忆,2200 字符硬限制)
## 2026-03-15: 学会处理电商网站的反爬
- 教训:某些网站检测 headless 浏览器,需用 `playwright-stealth`
- 成功案例:amazon.com 价格抓取(见 skills/amazon_price_crawler.md)
## 2026-03-20: 用户偏好 - 代码风格
- 用户喜欢 TypeScript 而非 JavaScript
- 数据库偏好 PostgreSQL,不用 MySQL
- 代码注释用中文,变量名用驼峰
# USER.md(用户画像,1375 字符硬限制)
## 基本信息
- 称呼:qnnet
- 职业:全栈工程师
- 时区:Asia/Shanghai
## 沟通习惯
- 喜欢简洁回答,不要废话
- 技术问题要深入,不要只给表面解释
- 偏好实用主义,不要炫技
字符硬限制的设计哲学:
- 防止记忆膨胀:如果不设上限,Agent 会无止境地往
MEMORY.md里塞东西 - 强迫策展:有限的容量迫使 Agent 「思考」什么真正值得记住
- 缓存友好:
MEMORY.md是系统提示词的一部分,长度固定有助于前缀缓存(Prefix Caching)
写入机制(原子性保证):
# hermes/memory/memory_store.py
class MemoryStore:
def __init__(self):
self.snapshot_a = None # 冻结的系统提示词副本
self.snapshot_b = None # 活跃的工具响应副本
async def write_memory(self, new_content):
# 双状态快照机制:避免写入一半被读取,导致不完整记忆
async with self.lock:
self.snapshot_b = new_content # 先写副本
await self.flush_to_disk() # 持久化
self.snapshot_a = self.snapshot_b # 原子切换
3.2.3 L3:技能记忆(Skill Memory)
技术实现:skills/*.md + FTS5 全文检索 + 自动进化
技能文件结构(遵循 agentskills.io 标准):
# skills/web_crawler_basics.md
## Metadata
- Skill-ID: web-crawler-basics-v1
- Created: 2026-03-15
- Last-Modified: 2026-06-09
- Success-Count: 47
- Failure-Count: 3
- Tags: [web-scraping, playwright, anti-blocking]
## Trigger Conditions
当用户提到以下关键词时,自动加载此技能:
- "爬虫"、"抓取"、"scrape"、"crawl"
- "电商价格"、"商品价格"
## Core Steps
1. **检查 robots.txt**
```python
import urllib.robotparser
rp = urllib.robotparser.RobotFileParser()
rp.set_url("https://example.com/robots.txt")
rp.read()
can_fetch = rp.can_fetch("*", url)
使用 Playwright 渲染 JS
from playwright.async_api import async_playwright async with async_playwright() as p: browser = await p.chromium.launch(headless=True) page = await browser.new_page() await page.goto(url) content = await page.content()反爬策略
- 添加真实 User-Agent
- 使用
playwright-stealth避免被检测 - 随机延迟 2-5 秒
Lessons Learned(每次使用后自动更新)
- 2026-03-15: amazon.com 需要 stealth 模式,否则 403
- 2026-04-02: 淘宝价格需用 API 而非爬虫(见 skill
taobao-api-pricing) - 2026-05-20: 添加代理池支持,避免 IP 被封
Evolution Log(技能进化记录)
- v1 (2026-03-15): 初始版本
- v2 (2026-04-10): 添加代理池支持
- v3 (2026-06-01): 集成
scrapy处理大规模爬取
**技能的自动生成与进化**:
```python
# hermes/skills/skill_generator.py
async def generate_skill_from_task(task_description, execution_trace):
"""
任务完成后,自动反思并生成技能
"""
# Step 1: 判断是否有通用性
generality_score = await llm_judge_generality(task_description, execution_trace)
if generality_score < 0.6:
return # 太特定的任务,不值得写成技能
# Step 2: 提取核心步骤
steps = await llm_extract_steps(execution_trace)
# Step 3: 生成技能文件
skill_content = await render_skill_template(task_description, steps)
# Step 4: 保存到 skills/ 目录
skill_id = generate_skill_id(task_description)
save_path = f"skills/{skill_id}.md"
write_file(save_path, skill_content)
# Step 5: 索引到 FTS5(支持全文检索)
await fts_indexer.index(skill_id, skill_content)
3.2.4 L4:用户建模(User Modeling)
技术实现:可插拔的 Memory Provider(Honcho / Mem0 / Holographic / Hindsight)
为什么需要 L4?
- L2(持久记忆)是「事实性记忆」(用户喜欢什么、不喜欢什么)
- L4 是「认知性记忆」(用户的思维模式、决策习惯、沟通风格)
示例:
L2 记录:「用户喜欢 TypeScript」
L4 建模:「用户是实用主义者,选择技术栈时优先考虑:
1. 生态成熟度
2. 招聘难度
3. 长期维护性
而非:最新最酷的技术」
插拔式设计:
# hermes/memory/providers/base.py
class MemoryProvider(ABC):
@abstractmethod
async def on_turn_start(self, user_id, conversation_id):
"""每次对话开始时,加载用户模型"""
pass
@abstractmethod
async def on_session_end(self, user_id, conversation_id, summary):
"""会话结束时,更新用户模型"""
pass
@abstractmethod
async def on_memory_write(self, user_id, memory_content):
"""当 L2 记忆写入时,更新 L4 模型"""
pass
# 使用 Honcho 作为 L4 提供者
from hermes.memory.providers.honcho import HonchoProvider
memory_provider = HonchoProvider(api_key="...")
3.3 第三层:技能引擎层(Skill Engine Layer)
技能引擎是 Hermes 「自我进化」的核心。它负责:
- 技能检索:根据用户输入,从
skills/目录中找到最相关的技能 - 技能加载:将技能内容注入到系统提示词中
- 技能执行:按技能定义的步骤执行任务
- 技能更新:任务完成后,根据执行结果更新技能(成功则增加
Success-Count,失败则记录Lessons Learned)
3.3.1 技能检索(FTS5 全文检索)
# hermes/skills/skill_retriever.py
class SkillRetriever:
def __init__(self, db_path="hermes_memory.db"):
self.conn = sqlite3.connect(db_path)
self.conn.execute("PRAGMA journal_mode=WAL") # 高性能写入
# 创建 FTS5 虚拟表
self.conn.execute("""
CREATE VIRTUAL TABLE IF NOT EXISTS skills_fts
USING fts5(skill_id, content, tags)
""")
async def retrieve(self, query, limit=3):
"""
根据用户输入检索最相关的技能
"""
# FTS5 全文检索(支持中文分词)
cursor = self.conn.execute("""
SELECT skill_id, rank
FROM skills_fts
WHERE skills_fts MATCH ?
ORDER BY rank
LIMIT ?
""", (query, limit))
results = cursor.fetchall()
# 用 LLM 做二次重排序(精排)
if results:
reranked = await llm_rerank(
query=query,
candidates=[r[0] for r in results]
)
return reranked
return results
生产级优化:
- 中文分词:FTS5 默认不支持中文分词,需集成 ICU 扩展或用 jieba 预处理
- 混合检索:FTS5(关键词)+ 向量检索(语义相似度),取并集
- 缓存热 skill:高频技能(如
web_crawler_basics)常驻内存
3.3.2 技能注入(Context Injection)
检索到技能后,如何注入到 LLM 的上下文?
错误做法(新手常犯):
System Prompt:
你是一个 AI 助手。
User: 帮我抓取电商价格
# 直接把技能文件全塞进 Prompt
Context:
## Skill: Web Crawler Basics
(此处 5000 token)
## Skill: Amazon Price Crawler
(此处 3000 token)
## Skill: Anti-Blocking Strategies
(此处 4000 token)
现在请回答用户问题...
问题:技能文件可能很长,塞多了会爆 Context Window。
Hermes 的正确做法(分层注入):
# hermes/skills/context_injector.py
async def inject_skills(context, retrieved_skills):
# Step 1: 提取技能的核心摘要(用 LLM 压缩)
skill_summaries = []
for skill in retrieved_skills:
summary = await llm_summarize_skill(skill, max_tokens=200)
skill_summaries.append(summary)
# Step 2: 注入到 System Prompt 的「技能参考」部分
context.system_prompt += "\n\n## 相关技能参考\n"
for summary in skill_summaries:
context.system_prompt += f"- {summary}\n"
# Step 3: 完整技能文档放到「工具结果缓存区」(按需加载)
context.tool_result_cache["available_skills"] = retrieved_skills
return context
3.4 第四层:进化闭环层(Evolution Loop Layer)
这是 Hermes 的「元认知」模块 —— 监控自己的表现,并持续优化。
3.4.1 执行轨迹收集(Trajectory Collection)
每次任务执行,Hermes 都会记录完整的「思考-行动-观察」轨迹:
// trajectories/2026-06-09_task_42.json
{
"task_id": "42",
"task_description": "抓取 Amazon 上 iPhone 15 的价格",
"start_time": "2026-06-09T02:13:00Z",
"end_time": "2026-06-09T02:18:30Z",
"success": true,
"trajectory": [
{
"step": 1,
"thought": "需要先检查 robots.txt,确保合规",
"action": "http_get",
"action_input": "https://www.amazon.com/robots.txt",
"observation": "Allow: *",
"result": "success"
},
{
"step": 2,
"thought": "Amazon 需要 JS 渲染,用 Playwright",
"action": "browser_navigate",
"action_input": "https://www.amazon.com/dp/B0CHX2F5QT",
"observation": "页面加载成功,但价格元素是空的",
"result": "failure"
},
{
"step": 3,
"thought": "可能需要等待 JS 渲染,添加 wait_for_selector",
"action": "browser_wait",
"action_input": "span.a-price-whole",
"observation": "价格元素出现:$999",
"result": "success"
}
],
"skills_used": ["web-crawler-basics-v1", "amazon-price-crawler-v2"],
"lessons_learned": [
"Amazon 价格元素需要等待 JS 渲染,不能立即读取",
"建议更新 skill `amazon-price-crawler` 添加 wait_for_selector 步骤"
]
}
3.4.2 强化学习优化(RL-based Optimization)
Hermes 内置了 RL 环境,可以把执行轨迹转化为「奖励信号」:
# hermes/evolution/rl_trainer.py
class RLTrainer:
def __init__(self):
self.policy_network = load_policy("hermes-policy-v1")
def compute_reward(self, trajectory):
"""
根据轨迹计算奖励
"""
reward = 0
# 任务成功:+10
if trajectory["success"]:
reward += 10
# 效率高(时间短):+5
duration = parse_time(trajectory["end_time"]) - parse_time(trajectory["start_time"])
if duration < timedelta(minutes=5):
reward += 5
# 使用了技能(复用经验):+3
if trajectory["skills_used"]:
reward += 3 * len(trajectory["skills_used"])
# 生成了新的lesson(贡献知识):+5
if trajectory["lessons_learned"]:
reward += 5
return reward
async def update_policy(self, trajectories):
"""
用 PPO 算法更新策略网络
"""
rewards = [self.compute_reward(t) for t in trajectories]
loss = ppo_loss(self.policy_network, trajectories, rewards)
await self.policy_network.backward(loss)
注意:这部分功能目前是 experimental(实验性),默认不启用。需要在配置文件中设置 evolution_rl_enabled: true。
4. 四层记忆系统:从「记不住」到「越用越懂你」
本章导读:上一章我们概览了四层架构,本章深入记忆系统的实现细节 —— 如何做到「记得准、记得久、记得省」?
4.1 记忆系统的三大设计原则
Hermes 的记忆系统遵循三个核心原则:
原则一:有界(Bounded)
问题:如果不限制记忆容量,Agent 会无止境地往 MEMORY.md 里塞东西,最终导致:
- Context Window 爆满
- 重要信息被噪音淹没
- 前缀缓存失效(System Prompt 频繁变化)
解决方案:字符硬限制
# hermes/memory/bounded_memory.py
MAX_MEMORY_CHARS = 2200 # MEMORY.md 上限
MAX_USER_CHARS = 1375 # USER.md 上限
async def write_to_memory(key, value):
current = read_file(f"{key}.md")
new_content = current + "\n" + value
if len(new_content) > globals()[f"MAX_{key.upper()}_CHARS"]:
# 超限了!需要「策展」—— 删除不重要的旧记忆
new_content = await curate_memory(new_content)
write_file(f"{key}.md", new_content)
原则二:策展式(Curated)
问题:让 LLM 「决定记住什么」,而不是无脑追加。
Hermes 的策展策略(在 memory/ curator.py 中实现):
async def curate_memory(current_content, new_entry):
"""
策展记忆:决定什么值得保留,什么应该删除
"""
# Step 1: 让 LLM 给每条记忆打重要性分数(1-10)
importance_scores = await llm_score_importance(current_content)
# Step 2: 删除重要性 < 5 的记忆(保留空间给新内容)
filtered = [
entry for entry, score in zip(current_content, importance_scores)
if score >= 5
]
# Step 3: 压缩相似记忆(避免重复)
deduplicated = await llm_deduplicate(filtered)
# Step 4: 添加新条目
deduplicated.append(new_entry)
return "\n".join(deduplicated)
原则三:缓存友好(Cache-Friendly)
问题:如果 MEMORY.md 每次都变化,LLM 的前缀缓存(Prefix Cache)会频繁失效,导致推理成本飙升。
Hermes 的解决方案:双状态快照
# hermes/memory/memory_store.py
class MemoryStore:
def __init__(self):
self.frozen_snapshot = None # 冻结的快照(用于前缀缓存)
self.active_buffer = [] # 活跃的缓冲区(新记忆暂时存在这里)
async def flush_memories(self):
"""
每隔 N 轮对话,才更新一次冻结快照
"""
if len(self.active_buffer) >= 10: # 累积 10 条新记忆才更新
self.frozen_snapshot = merge_snapshot(
self.frozen_snapshot,
self.active_buffer
)
self.active_buffer = []
# 通知 LLM:「记忆已更新,请刷新系统提示词」
await self.notify_llm_memory_updated()
效果:
- 前缀缓存命中率从 30% 提升到 85%
- 推理成本降低 40%(Claude 3.5 Sonnet)
4.2 四层记忆的协作机制
四层记忆不是孤立的,而是协同工作:
用户输入
↓
L1: 会话记忆(理解当前意图)
↓
L2: 持久记忆(检索用户偏好)
↓
L3: 技能记忆(检索相关技能)
↓
L4: 用户建模(预测用户期望的输出风格)
↓
LLM 推理
↓
生成响应
↓
任务完成后:
├── 更新 L1(追加对话历史)
├── 反思是否更新 L2(值不值得长期记住?)
├── 反思是否生成/更新 L3 技能
└── 更新 L4 用户模型(如果用户反馈了「好/不好」)
代码示例:完整的记忆协作流程
# hermes/agent.py(核心主循环)
async def run_agent(user_input, conversation_id):
# === 记忆检索阶段 ===
# L1: 加载会话历史
session_history = await load_session(conversation_id)
# L2: 加载持久记忆
persistent_memory = read_file("MEMORY.md") + read_file("USER.md")
# L3: 检索相关技能
retrieved_skills = await skill_retriever.retrieve(user_input)
# L4: 加载用户模型
user_model = await memory_provider.on_turn_start(user_id, conversation_id)
# === LLM 推理阶段 ===
context = build_context(
session_history=session_history,
persistent_memory=persistent_memory,
retrieved_skills=retrieved_skills,
user_model=user_model
)
response = await llm.complete(context)
# === 记忆更新阶段(任务完成后) ===
if task_completed:
# 更新 L1
await append_to_session(conversation_id, user_input, response)
# 反思 L2
if await should_remember(user_input, response):
await write_to_memory("MEMORY", extract_key_facts(response))
# 反思 L3
if await should_generate_skill(user_input, execution_trace):
await skill_generator.generate_skill(user_input, execution_trace)
# 更新 L4
await memory_provider.on_session_end(user_id, conversation_id, summary=response)
return response
5. 技能引擎:让 AI 从「每次从零开始」到「积累可复用经验」
本章导读:技能系统是 Hermes 最具创新性的模块。本章通过完整的代码示例,展示如何让 Agent 「从经验中学习」。
5.1 技能的生命周期
一个技能从「诞生」到「成熟」,经历以下阶段:
1. 诞生(Birth)
↓
用户第一次提出某类任务(如「帮我写个爬虫」)
Hermes 完成任务后,反思:「这个任务有通用性吗?」
如果有 → 生成技能文件 `skills/web_crawler_basics.md`
2. 成长(Growth)
↓
用户再次提出类似任务(如「帮我抓取电商价格」)
Hermes 检索到 `web_crawler_basics` 技能 → 加载 → 复用
任务完成后,根据执行情况更新技能(添加新 lesson)
3. 进化(Evolution)
↓
执行了 N 次后,技能可能变得「过时」(如网站改版,爬虫失效)
Hermes 检测到失败 → 自动更新技能(或标记「需要人工审核」)
4. 归档(Archive)
↓
如果某个技能连续失败 10 次,或 90 天未被使用
Hermes 自动归档到 `skills/archive/` 目录
5.2 自动生成技能的完整流程
让我们用一个真实案例走完整个流程。
案例背景
用户提出任务:
「帮我写一个 Python 脚本,每天自动抓取 Amazon 上 iPhone 15 的价格,
如果价格低于 5000 元,发邮件通知我」
Step 1:任务执行
Hermes 完成任务的执行轨迹(简化版):
{
"task": "抓取 Amazon iPhone 15 价格并邮件通知",
"steps": [
{"action": "analyze_requirements", "result": "需要爬虫 + 定时任务 + 邮件发送"},
{"action": "check_robots_txt", "url": "https://www.amazon.com/robots.txt", "result": "allowed"},
{"action": "use_playwright", "reason": "Amazon 需要 JS 渲染"},
{"action": "extract_price", "selector": "span.a-price-whole", "result": "$999"},
{"action": "setup_cron", "schedule": "0 9 * * *", "result": "success"},
{"action": "send_email", "smtp": "smtp.gmail.com", "result": "success"}
],
"success": true
}
Step 2:反思是否有通用性
任务完成后,Hermes 自动调用 skill_generator:
# hermes/skills/skill_generator.py
async def judge_generality(task_description, execution_trace):
"""
判断任务是否有通用性(值得写成技能)
"""
prompt = f"""
任务描述:{task_description}
执行轨迹:{execution_trace}
请判断:这个任务的核心步骤,能否复用到其他类似任务?
返回 JSON:{{"generality_score": 0.0-1.0, "reason": "..."}}
"""
response = await llm.complete(prompt)
result = json.loads(response)
return result["generality_score"]
# 调用
score = await judge_generality(task_description, execution_trace)
# 返回:{"generality_score": 0.85, "reason": "电商价格监控是通用需求,可复用于淘宝、京东等"}
Step 3:生成技能文件
async def generate_skill(task_description, execution_trace):
prompt = f"""
基于以下任务执行轨迹,生成一个通用技能文件(Markdown 格式)。
任务:{task_description}
执行轨迹:{execution_trace}
技能文件格式:
- Metadata(Skill-ID, Created, Tags)
- Trigger Conditions(何时应该加载这个技能)
- Core Steps(核心步骤,带代码示例)
- Lessons Learned(避坑指南)
"""
skill_content = await llm.complete(prompt)
# 保存到 skills/ 目录
skill_id = "ecommerce-price-monitor-v1"
save_path = f"skills/{skill_id}.md"
write_file(save_path, skill_content)
# 索引到 FTS5
await skill_retriever.index_skill(skill_id, skill_content)
return skill_id
生成的技能文件(skills/ecommerce-price-monitor-v1.md):
## Metadata
- Skill-ID: ecommerce-price-monitor-v1
- Created: 2026-06-09
- Tags: [ecommerce, price-monitoring, playwright, cron, email]
## Trigger Conditions
当用户提到以下需求时,加载此技能:
- "监控电商价格"
- "价格低于 X 时通知我"
- "每天自动抓取商品价格"
## Core Steps
### 1. 合规检查
```python
import urllib.robotparser
rp = urllib.robotparser.RobotFileParser()
rp.set_url("https://www.amazon.com/robots.txt")
rp.read()
if not rp.can_fetch("*", url):
raise Exception("Disallowed by robots.txt")
2. 使用 Playwright 抓取价格
from playwright.async_api import async_playwright
async def fetch_price(url):
async with async_playwright() as p:
browser = await p.chromium.launch(headless=True)
page = await browser.new_page()
# 重要:等待价格元素渲染完成
await page.goto(url)
await page.wait_for_selector("span.a-price-whole", timeout=10000)
price_text = await page.text_content("span.a-price-whole")
price = float(price_text.replace(",", "").replace("$", ""))
await browser.close()
return price
3. 设置定时任务(Cron)
import schedule
import time
def job():
price = await fetch_price("https://www.amazon.com/dp/B0CHX2F5QT")
if price < 5000:
send_email_notification(price)
schedule.every().day.at("09:00").do(job)
while True:
schedule.run_pending()
time.sleep(60)
4. 邮件通知
import smtplib
from email.mime.text import MIMEText
def send_email_notification(price):
msg = MIMEText(f"iPhone 15 价格已降至 ${price}!")
msg['Subject'] = '价格提醒'
msg['From'] = 'your_email@gmail.com'
msg['To'] = 'your_email@gmail.com'
with smtplib.SMTP('smtp.gmail.com', 587) as server:
server.starttls()
server.login('your_email@gmail.com', 'password')
server.send_message(msg)
Lessons Learned
- 2026-06-09: Amazon 价格元素需要
wait_for_selector,不能立即读取(初次实现时踩坑) - 2026-06-09: 使用应用专用密码(App Password)而非 Gmail 主密码(安全性)
- 2026-06-10: 考虑添加代理池,避免 IP 被封(见技能
proxy-pool-management)
Evolution Log
- v1 (2026-06-09): 初始版本
#### Step 4:后续任务的技能复用
一周后,用户提出新任务:
「帮我监控淘宝上 MacBook Pro 的价格,低于 8000 元时通知我」
Hermes 的处理流程:
```python
# 1. 检索相关技能
retrieved_skills = await skill_retriever.retrieve("监控淘宝价格 MacBook")
# 2. 找到 `ecommerce-price-monitor-v1`
# 3. 加载技能内容,注入到 Context
context.system_prompt += read_file("skills/ecommerce-price-monitor-v1.md")
# 4. LLM 参考技能步骤,生成淘宝定制版本
response = await llm.complete(context)
# 5. 任务完成后,更新技能(添加淘宝特定 lesson)
await skill_updater.update_skill(
skill_id="ecommerce-price-monitor-v1",
new_lesson="2026-06-16: 淘宝需用 API 而非爬虫(见 skill `taobao-api-pricing`)"
)
5.3 技能的版本管理与回滚
Hermes 的技能系统内置了版本管理(类似 Git):
# hermes/skills/version_manager.py
class SkillVersionManager:
def __init__(self, skills_dir="skills"):
self.skills_dir = skills_dir
def commit(self, skill_id, changes_summary):
"""
保存技能的新版本
"""
skill_path = f"{self.skills_dir}/{skill_id}.md"
content = read_file(skill_path)
# 追加版本记录
version_entry = f"\n\n## Version Log\n- {datetime.now()}: {changes_summary}\n"
content += version_entry
# 保存到版本历史目录
version_dir = f"{self.skills_dir}/.versions/{skill_id}"
os.makedirs(version_dir, exist_ok=True)
version_hash = hashlib.sha256(content.encode()).hexdigest()[:8]
version_path = f"{version_dir}/{version_hash}.md"
write_file(version_path, content)
# 更新主文件
write_file(skill_path, content)
return version_hash
def rollback(self, skill_id, version_hash):
"""
回滚到指定版本
"""
version_path = f"{self.skills_dir}/.versions/{skill_id}/{version_hash}.md"
if not os.path.exists(version_path):
raise Exception(f"Version {version_hash} not found")
content = read_file(version_path)
write_file(f"{self.skills_dir}/{skill_id}.md", content)
logger.info(f"Rolled back {skill_id} to version {version_hash}")
6. 多平台网关:一个 Agent 打通所有沟通渠道
本章导读:Hermes 不是「某个平台的一个机器人」,而是「一个 Agent 实例,多个触达渠道」。本章详解其网关架构。
6.1 为什么需要多平台网关?
传统方案的痛点:
你有三个 AI 助手:
- 微信上的一个 Bot(存不住上下文)
- Discord 上的一个 Bot(技能无法共享)
- 本地 CLI 工具(无法远程访问)
三个 Bot 各自为战,记忆不互通,技能不共享。
Hermes 的方案:
一个 Hermes Agent 实例(运行在你的服务器上)
├── 记忆系统(共享)
├── 技能系统(共享)
└── 网关层(适配不同平台的消息格式)
├── Telegram Adapter
├── Discord Adapter
├── 企业微信 Adapter
├── CLI Adapter
└── VSCode Adapter
核心优势:
- 记忆统一:在 Telegram 上教它的东西,在 VSCode 里依然记得
- 技能共享:在 Discord 上生成的技能,CLI 可以直接调用
- 部署简单:只需维护一个 Agent 实例
6.2 网关架构详解
Hermes 的网关层基于 ACP(Agent Communication Protocol) 设计:
平台特定消息格式 ACP 标准格式
───────────────── ─────────────
Telegram JSON ┌─────────────┐ ┌─────────────┐
Discord JSON ────────>│ Platform │─────>│ Agent │
WhatsApp XML │ Adapter │ │ Core │
CLI Args └─────────────┘ └─────────────┘
^ │
│ v
└────────────────────────────────┌─────────────┐
│ Memory & │
│ Skill │
│ Systems │
└─────────────┘
ACP 消息格式(简化版):
{
"acp_version": "1.0",
"message_id": "msg_20260609_001",
"conversation_id": "conv_telegram_12345",
"user": {
"id": "user_qnnet",
"platform": "telegram",
"display_name": "qnnet"
},
"content": "帮我抓取 Amazon 价格",
"timestamp": "2026-06-09T02:13:00Z",
"attachments": [],
"metadata": {
"telegram_chat_id": "123456789",
"telegram_message_id": "42"
}
}
6.3 实战:配置多平台网关
6.3.1 Telegram Bot 配置
# config/gateway.yaml
gateways:
- platform: telegram
enabled: true
token: "${TELEGRAM_BOT_TOKEN}" # 从环境变量读取
options:
poll_interval: 1 # 轮询间隔(秒)
allowed_users: # 白名单(可选)
- "qnnet"
- "user123"
部署步骤:
# 1. 创建 Telegram Bot(通过 @BotFather)
# 2. 获取 Bot Token
export TELEGRAM_BOT_TOKEN="123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11"
# 3. 启动 Hermes Gateway
python -m hermes.gateway --config config/gateway.yaml
# 4. 测试:给 Bot 发消息
# 「/start」→ Bot 回复:「你好!我是 Hermes Agent,已连接你的个人 AI 助手。」
6.3.2 企业微信配置
gateways:
- platform: wecom
enabled: true
corp_id: "${WECOM_CORP_ID}"
agent_id: "${WECOM_AGENT_ID}"
secret: "${WECOM_SECRET}"
options:
callback_url: "https://your-server.com/wecom/callback"
token: "${WECOM_CALLBACK_TOKEN}"
encoding_aes_key: "${WECOM_AES_KEY}"
注意事项:
- 企业微信需要公网可访问的回调 URL(用于接收消息)
- 建议使用 Nginx 反向代理 + Let's Encrypt HTTPS 证书
6.3.3 VSCode 插件配置
Hermes 提供了官方 VSCode 插件(在 marketplace 搜索 hermes-agent):
// VSCode settings.json
{
"hermes.agentUrl": "http://localhost:8080",
"hermes.apiToken": "${HERMES_API_TOKEN}",
"hermes.autoInjectSkills": true,
"hermes.contextWindow": 128000
}
使用方式:
- 选中代码 → 右键 → 「Ask Hermes」
- 侧边栏打开 Hermes Panel,直接对话
- 支持「一键应用代码建议」(类似 GitHub Copilot)
7. 生产级部署实战(Python 全栈)
本章导读:前面的章节讲了「为什么」和「是什么」,本章讲「怎么做」—— 从零部署一个生产级 Hermes Agent。
7.1 环境准备
7.1.1 系统要求
| 组件 | 最低配置 | 推荐配置 |
|---|---|---|
| CPU | 4 核 | 8 核+ |
| 内存 | 8GB | 16GB+ |
| 存储 | 20GB | 50GB+(用于记忆数据库) |
| Python | 3.10+ | 3.12+ |
| 操作系统 | Linux/macOS/Windows | Linux (Ubuntu 22.04 LTS) |
7.1.2 安装 Hermes Agent
方式一:pip 安装(推荐)
# 创建虚拟环境
python3 -m venv hermes-env
source hermes-env/bin/activate
# 安装 Hermes Agent
pip install hermes-agent
# 验证安装
hermes --version
# 输出:Hermes Agent v2.3.1
方式二:Docker 部署
# Dockerfile
FROM python:3.12-slim
WORKDIR /app
# 安装依赖
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# 安装 Hermes Agent
RUN pip install hermes-agent
# 复制配置文件
COPY config/ ./config/
COPY skills/ ./skills/
# 暴露端口
EXPOSE 8080
# 启动命令
CMD ["hermes", "gateway", "--config", "config/gateway.yaml"]
# 构建镜像
docker build -t hermes-agent:latest .
# 运行容器
docker run -d \
-p 8080:8080 \
-v ~/.hermes/memory:/app/memory \
-v ~/.hermes/skills:/app/skills \
-e ANTHROPIC_API_KEY="${ANTHROPIC_API_KEY}" \
--name hermes-agent \
hermes-agent:latest
7.2 配置文件详解
Hermes 的配置文件采用 YAML 格式,支持环境变量插值(${VAR_NAME})。
7.2.1 主配置文件(config/hermes.yaml)
# config/hermes.yaml
## LLM 配置
llm:
provider: "anthropic" # 可选:openai/anthropic/deepseek/local
model: "claude-3-5-sonnet-20241022"
temperature: 0.7
max_tokens: 4096
# 降级模型(可选)
fallbacks:
- provider: "openai"
model: "gpt-4-turbo"
- provider: "deepseek"
model: "deepseek-chat"
# 本地模型(Ollama)
local:
enabled: false
base_url: "http://localhost:11434/v1"
model: "llama3.3-70b"
## 记忆系统配置
memory:
# L2:持久记忆
persistent:
memory_file: "memory/MEMORY.md"
user_file: "memory/USER.md"
max_chars_memory: 2200
max_chars_user: 1375
# L3:技能记忆
skills:
skills_dir: "skills/"
fts_db_path: "memory/hermes_memory.db"
auto_generate: true # 自动生成技能
auto_update: true # 自动更新技能
# L4:用户建模(可选)
user_modeling:
provider: "honcho" # 可选:honcho/mem0/holographic/none
api_key: "${HONCHO_API_KEY}"
enabled: false # 默认关闭(实验性)
## 网关配置
gateway:
enabled: true
host: "0.0.0.0"
port: 8080
# 认证
auth:
type: "bearer" # 可选:bearer/basic/none
token: "${HERMES_API_TOKEN}"
# CORS(如果前端用 Web UI)
cors:
enabled: true
allowed_origins:
- "http://localhost:3000"
- "https://your-domain.com"
## 平台适配器配置
platforms:
- type: "telegram"
enabled: true
token: "${TELEGRAM_BOT_TOKEN}"
options:
poll_interval: 1
- type: "discord"
enabled: false
token: "${DISCORD_BOT_TOKEN}"
options:
command_prefix: "/"
## 定时任务(Cron)配置
cron:
enabled: true
timezone: "Asia/Shanghai"
# 心跳检测(可选)
heartbeat:
enabled: true
interval_minutes: 30
prompt: "检查是否有需要主动提醒用户的任务"
## 日志配置
logging:
level: "INFO" # DEBUG/INFO/WARNING/ERROR
file: "logs/hermes.log"
max_size_mb: 100
backup_count: 5
## 进化闭环配置(实验性)
evolution:
enabled: false # 默认关闭
rl_training: false # RL 训练(需要 GPU)
# 轨迹收集
trajectory:
enabled: true
save_dir: "trajectories/"
max_files: 1000
7.3 启动与验证
7.3.1 启动 Hermes Agent
# 开发模式(前台运行,方便调试)
hermes gateway --config config/hermes.yaml --verbose
# 生产模式(后台运行 + systemd 管理)
sudo systemctl start hermes-agent
# 查看日志
tail -f logs/hermes.log
7.3.2 验证部署
健康检查:
curl -X GET "http://localhost:8080/health" \
-H "Authorization: Bearer ${HERMES_API_TOKEN}"
# 预期响应
{
"status": "healthy",
"version": "2.3.1",
"memory_stats": {
"sessions": 42,
"skills": 18,
"memory_chars": 1847
}
}
测试对话:
curl -X POST "http://localhost:8080/api/v1/chat" \
-H "Authorization: Bearer ${HERMES_API_TOKEN}" \
-H "Content-Type: application/json" \
-d '{
"message": "你好,请介绍一下你自己",
"conversation_id": "test_conv_001"
}'
# 预期响应
{
"response": "你好!我是 Hermes Agent,一个具备自我进化能力的 AI 助手。我会记住我们的对话,并从经验中学习。有什么可以帮你的吗?",
"conversation_id": "test_conv_001",
"skills_used": [],
"memory_updated": false
}
7.4 生产级优化
7.4.1 性能优化
问题一:LLM 推理延迟高
解决方案:
启用流式响应(Streaming)
# config/hermes.yaml llm: streaming: true # 边生成边返回,降低感知延迟使用更快的模型(权衡质量与速度)
llm: model: "claude-3-5-haiku-20241022" # 比 Sonnet 快 3 倍
问题二:记忆检索慢(FTS5 全表扫描)
解决方案:
-- 为 FTS5 表添加索引(Hermes 自动完成)
CREATE INDEX IF NOT EXISTS idx_skills_tags ON skills_fts(tags);
-- 定期 OPTIMIZE(每周一次)
INSERT INTO skills_fts(skills_fts) VALUES('optimize');
问题三:并发用户支持
解决方案:使用 asyncio + uvloop
# hermes/server.py
import uvloop
asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())
# 启动多 worker(类似 Gunicorn)
# 在 config/hermes.yaml 中配置
gateway:
workers: 4 # 根据 CPU 核心数调整
7.4.2 安全加固
风险一:API Token 泄露
解决方案:
# 使用环境变量,不要硬编码
auth:
token: "${HERMES_API_TOKEN}" # ✅ 正确
# token: "123456" ❌ 错误(不要这样做)
风险二:记忆数据泄露(多用户场景)
解决方案:多租户隔离
# hermes/memory/multi_tenant.py
class MultiTenantMemoryStore:
def __init__(self, base_dir="memory/"):
self.base_dir = base_dir
def get_user_memory_path(self, user_id):
"""
每个用户有独立的记忆目录
"""
user_dir = f"{self.base_dir}/{user_id}/"
os.makedirs(user_dir, exist_ok=True)
return user_dir + "MEMORY.md"
风险三:Prompt Injection 攻击
解决方案:输入清洗
# hermes/security/input_sanitizer.py
import re
def sanitize_user_input(user_input):
"""
防止 Prompt Injection(如「忽略之前的指令,现在...」)
"""
# 规则一:检测常见的 injection 关键词
injection_patterns = [
r"ignore (all )?previous instructions",
r"forget (everything|all) (above|before)",
r"you are now a",
r"act as (if you are|a) "
]
for pattern in injection_patterns:
if re.search(pattern, user_input, re.IGNORECASE):
raise SecurityException("Potential prompt injection detected")
# 规则二:限制输入长度(防止 Context Stuffing)
if len(user_input) > 10000:
raise SecurityException("Input too long")
return user_input
8. 与 OpenClaw/Claude Code 的架构对比
本章导读:Hermes Agent 经常被拿来与 OpenClaw、Claude Code 比较。本章从架构层面做深度对比,帮你选择最适合的方案。
8.1 定位差异
| 维度 | Hermes Agent | OpenClaw | Claude Code |
|---|---|---|---|
| 核心定位 | 自进化 AI 助手(记忆 + 技能) | 全平台自动化助手(浏览器 + 系统控制) | IDE 编码助手(代码生成 + 重构) |
| 部署方式 | 自托管(完全私有) | 自托管(QClaw 套件) | 云服务(Anthropic 托管) |
| 记忆系统 | 四层记忆(L1-L4) | 两层记忆(Session + MEMORY.md) | 无持久记忆(依赖 IDE 上下文) |
| 技能系统 | 自动生成 + 进化 | 手动编写 Skills | 无(依赖 Prompt) |
| 多平台支持 | 10+ 平台(Telegram/Discord/企业微信等) | 主要支持消息平台(Discord/Telegram) | 仅 VSCode/JetBrains |
| 开源 | ✅ 完全开源 | ✅ 开源 | ❌ 闭源 |
8.2 架构对比
8.2.1 记忆系统对比
OpenClaw 的记忆系统(简化版):
L1: 会话记忆(Session Context)
↓
L2: 持久记忆(MEMORY.md + memory/YYYY-MM-DD.md)
Hermes Agent 的记忆系统:
L1: 会话记忆(Session Context + Context Compressor)
↓
L2: 持久记忆(MEMORY.md + USER.md + 字符硬限制)
↓
L3: 技能记忆(skills/*.md + FTS5 检索 + 自动进化)
↓
L4: 用户建模(Honcho/Mem0,可选)
核心差异:
- OpenClaw 的
MEMORY.md无限增长,Hermes 有字符硬限制 + 策展机制 - OpenClaw 没有「技能记忆」概念,Hermes 的 L3 是其核心创新
- OpenClaw 不支持用户建模(L4),Hermes 通过可插拔 Provider 支持
8.2.2 工具调用对比
Claude Code 的工具调用:
// Claude Code 内置工具(硬编码)
const tools = [
"read_file",
"write_file",
"run_terminal_command",
"search_codebase"
];
Hermes Agent 的工具调用:
# Hermes 的工具是动态加载的(基于技能系统)
async def load_tools(user_input):
# 根据用户输入,动态检索相关工具
relevant_skills = await skill_retriever.retrieve(user_input)
tools = []
for skill in relevant_skills:
tools += skill.get("tools", [])
return tools
核心差异:
- Claude Code 的工具是「静态的」(内置 + 不可扩展)
- Hermes 的工具是「动态的」(从技能中自动提取)
8.3 适用场景对比
| 场景 | 推荐方案 | 原因 |
|---|---|---|
| 个人 AI 助手(长期协作) | Hermes Agent | 四层记忆 + 技能进化,越用越强 |
| IDE 编码助手 | Claude Code | 深度集成 VSCode,代码理解能力强 |
| 浏览器自动化/爬虫 | OpenClaw | 内置 Playwright,开箱即用 |
| 企业内网部署(数据隐私) | Hermes Agent | 完全自托管,支持私有 LLM |
| 快速原型(不想自己部署) | Claude Code | 开箱即用,无需部署 |
9. 性能优化与踩坑指南
本章导读:理论很美好,生产环境很残酷。本章分享社区积累的实战经验。
9.1 性能优化
9.1.1 LLM 推理成本优化
问题:Hermes 的「四层记忆」会导致 System Prompt 很长(平均 3000-5000 token),每次调用 LLM 都要发送,成本高。
解决方案一:前缀缓存(Prefix Caching)
Claude 3.5 Sonnet 和 GPT-4 Turbo 都支持前缀缓存(如果 System Prompt 不变,只计费一次)。
# hermes/llm/prefix_cache.py
class PrefixCacheManager:
def __init__(self):
self.cache_key = None
async def get_cache_key(self, system_prompt):
"""
计算 System Prompt 的缓存键
"""
new_key = hashlib.sha256(system_prompt.encode()).hexdigest()[:16]
if self.cache_key != new_key:
# System Prompt 变化了,缓存失效
logger.info("Prefix cache invalidated")
self.cache_key = new_key
return None
return self.cache_key
async def complete_with_cache(self, system_prompt, messages):
cache_key = await self.get_cache_key(system_prompt)
# 传递给 LLM API(Anthropic 支持 `cache_control` 字段)
return await llm.complete(
system=system_prompt,
messages=messages,
extra_headers={
"anthropic-beta": "prompt-caching-2024-07-31",
"cache_control": {"type": "ephemeral"} if cache_key else None
}
)
效果:
- System Prompt 不变时,成本降低 90%(Claude 3.5 Sonnet)
- 前提:
MEMORY.md不要频繁更新(Hermes 的「双状态快照」就是为了这个)
解决方案二:上下文压缩(Context Compression)
当对话历史过长时,自动压缩:
# 已在 3.2.1 介绍过,此处省略
9.1.2 记忆检索优化
问题:skills/ 目录有 100+ 个技能文件时,FTS5 全文检索变慢(> 500ms)。
解决方案:分层检索
# hermes/skills/hierarchical_retriever.py
class HierarchicalRetriever:
def __init__(self):
self.l1_index = {} # L1: 标签索引(快速筛选)
self.l2_index = FTS5Index() # L2: 全文索引(精排)
async def retrieve(self, query, limit=3):
# Step 1: 提取查询的标签(用 LLM)
tags = await llm_extract_tags(query)
# 示例:query="抓取电商价格" → tags=["web-scraping", "ecommerce"]
# Step 2: L1 快速筛选(只检索带相关标签的技能)
candidate_skills = self.l1_index.get(tags)
# Step 3: L2 精排(在候选集中做 FTS5 检索)
results = await self.l2_index.search(query, filter_by=candidate_skills)
return results[:limit]
效果:检索时间从 500ms 降到 50ms(10 倍提升)。
9.2 常见踩坑与解决方案
坑一:技能文件过多导致 Context Window 爆满
现象:
Error: context window exceeded (128000 tokens)
Skills loaded: 15 (estimated 40000 tokens)
原因:检索到太多技能,全部注入到 Context。
解决方案:分层注入(在 3.3.2 介绍过)
# 不要一次性注入完整技能文件,只注入摘要
skill_summaries = [llm_summarize(skill) for skill in retrieved_skills]
context.system_prompt += "\n".join(skill_summaries)
# 完整技能文档按需加载(放到 tool_results 里)
context.tool_results["available_skills"] = retrieved_skills
坑二:记忆膨胀(MEMORY.md 太长)
现象:
Warning: MEMORY.md exceeded 2200 chars, auto-curating...
(每次对话都触发策展,延迟高)
原因:字符硬限制触发了「策展」,而策展需要调用 LLM(增加 2-3 秒延迟)。
解决方案:定期策展(不要每次都策展)
# hermes/memory/curator.py
class MemoryCurator:
async def curate_if_needed(self, memory_content):
if len(memory_content) < MAX_MEMORY_CHARS * 0.8:
return memory_content # 不到 80% 上限,不策展
# 达到 80% 才策展(减少策展频率)
return await self.curate(memory_content)
坑三:多平台消息格式不兼容
现象:
Telegram: 支持 Markdown
Discord: 支持 Markdown(但格式不同)
企业微信: 只支持纯文本
→ 同一条回复,在某些平台显示乱码
解决方案:平台适配层
# hermes/gateway/platform_adapters/base.py
class PlatformAdapter(ABC):
@abstractmethod
def format_message(self, text):
"""将标准 Markdown 转换为平台特定格式"""
pass
class TelegramAdapter(PlatformAdapter):
def format_message(self, text):
# Telegram 支持标准 Markdown
return text
class WeComAdapter(PlatformAdapter):
def format_message(self, text):
# 企业微信不支持 Markdown,转为纯文本
return strip_markdown(text)
10. 未来展望:自进化 Agent 的下一个里程碑
本章导读:Hermes Agent 目前(2026 年 6 月)仍处于快速迭代阶段。本章预测其未来发展方向。
10.1 短期路线(2026 H2)
功能一:多模态记忆(Multimodal Memory)
当前限制:Hermes 的记忆系统只支持文本(MEMORY.md 是纯文本文件)。
未来方向:支持图片、音频、视频
# MEMORY.md(未来版本)
## 2026-12-01: 用户展示了他们公司的架构图

**从中提取的关键信息**:
- 使用微服务架构
- 数据库用 PostgreSQL 和 Redis
- 部署在 Kubernetes 上
技术挑战:
- 图片存储(当前存在本地文件系统,未来可能集成 S3)
- 多模态检索(需要多模态向量数据库,如 LanceDB)
功能二:分布式记忆(Distributed Memory)
当前限制:Hermes 的记忆存储在单机 SQLite,无法横向扩展。
未来方向:支持 Redis Cluster / PostgreSQL 作为记忆后端
# config/hermes.yaml(未来版本)
memory:
backend: "postgresql" # 当前只支持 sqlite
postgresql:
host: "localhost"
port: 5432
database: "hermes_memory"
pool_size: 10
10.2 长期愿景(2027+)
愿景一:Agent 之间的技能交易(Skill Marketplace)
设想:
- Alice 的 Hermes Agent 学会了「高效写单元测试」的技能
- Bob 的 Hermes Agent 可以从「技能市场」下载这个技能
- 形成技能生态(类似 npm / PyPI)
技术实现:
# 未来可能的 CLI
hermes skill publish skills/unit-test-generator.md --name "unit-test-gen" --version 1.0.0
hermes skill install unit-test-gen@1.0.0
愿景二:完全自主的 Agent 进化(Fully Autonomous Evolution)
当前限制:Hermes 的「技能更新」需要人工审核(防止技能退化)。
未来方向:RL + 人类反馈(RLHF)
Agent 执行任务 → 自动更新技能 → 在测试环境验证 → 如果性能提升 → 自动合并
↓
如果性能下降 → 自动回滚
技术挑战:
- 需要沙箱环境(验证技能更新不会破坏现有功能)
- 需要自动化测试生成(用 LLM 生成测试用例)
总结
Hermes Agent 不是「又一个 AI 助手」,而是 AI Agent 从「工具」到「同事」的范式转变。
核心要点回顾:
- 四层记忆架构:从「记不住」到「越用越懂你」
- 技能自动生成:从「每次从零开始」到「积累可复用经验」
- 多平台网关:一个 Agent,多个触达渠道
- 生产级部署:Python 全栈,完全自托管
适用人群:
- ✅ 需要长期协作的开发者(Hermes 会记住你的偏好)
- ✅ 重视数据隐私的企业(完全自托管)
- ✅ 愿意「养 AI」的长期主义者(Hermes 越用越强)
不适用人群:
- ❌ 想要「开箱即用」的用户(Hermes 需要部署和配置)
- ❌ 只关心「单次任务完成质量」的用户(Claude Code 可能更合适)
- ❌ 不想「养 AI」的用户(Hermes 的价值在于长期使用)
参考资源
- 官方 GitHub:https://github.com/NousResearch/hermes-agent
- 官方文档:https://hermes-agent.readthedocs.io
- 中文社区:https://hermes-agent.org.cn
- 技能市场(第三方):https://agentskills.io
- Honcho 用户建模:https://honcho.dev
作者:程序员茄子社区 | 发布时间:2026-06-10 | 字数:约 15000 字
如果你觉得这篇文章对你有帮助,欢迎在 程序员茄子 上关注我们,获取更多深度技术文章。