编程 Hermes Agent 深度实战:当 AI 学会「自我进化」——从四层记忆架构到生产级部署的完全指南(2026)

2026-06-10 02:17:49 +0800 CST views 10

Hermes Agent 深度实战:当 AI 学会「自我进化」——从四层记忆架构到生产级部署的完全指南(2026)

作者按:Hermes Agent 是 2026 年 AI Agent 领域最具颠覆性的开源项目。它不是另一个「调用 API 的壳」,而是一个真正具备自我进化能力的数字员工。本文将深入剖析其四层记忆架构、技能自动生成机制、多平台网关设计,并通过完整的 Python 代码示例,带你从零到生产级部署。


目录

  1. 为什么需要「会进化」的 AI Agent?
  2. Hermes Agent 是什么?核心定位解析
  3. 四层自进化闭环架构深度拆解
  4. 四层记忆系统:从「记不住」到「越用越懂你」
  5. 技能引擎:让 AI 从「每次从零开始」到「积累可复用经验」
  6. 多平台网关:一个 Agent 打通所有沟通渠道
  7. 生产级部署实战(Python 全栈)
  8. 与 OpenClaw/Claude Code 的架构对比
  9. 性能优化与踩坑指南
  10. 未来展望:自进化 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 会自动反思

  1. 这次任务中,哪些步骤是通用的?
  2. 能否把这些步骤提炼成可复用的「技能」(Skill)?
  3. 下次遇到类似任务,能否直接调用这个技能?

示例

# 你让 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)
  1. 使用 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()
    
  2. 反爬策略

    • 添加真实 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 「自我进化」的核心。它负责:

  1. 技能检索:根据用户输入,从 skills/ 目录中找到最相关的技能
  2. 技能加载:将技能内容注入到系统提示词中
  3. 技能执行:按技能定义的步骤执行任务
  4. 技能更新:任务完成后,根据执行结果更新技能(成功则增加 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 里塞东西,最终导致:

  1. Context Window 爆满
  2. 重要信息被噪音淹没
  3. 前缀缓存失效(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

核心优势

  1. 记忆统一:在 Telegram 上教它的东西,在 VSCode 里依然记得
  2. 技能共享:在 Discord 上生成的技能,CLI 可以直接调用
  3. 部署简单:只需维护一个 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 系统要求

组件最低配置推荐配置
CPU4 核8 核+
内存8GB16GB+
存储20GB50GB+(用于记忆数据库)
Python3.10+3.12+
操作系统Linux/macOS/WindowsLinux (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 推理延迟高

解决方案

  1. 启用流式响应(Streaming)

    # config/hermes.yaml
    llm:
      streaming: true  # 边生成边返回,降低感知延迟
    
  2. 使用更快的模型(权衡质量与速度)

    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 AgentOpenClawClaude 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: 用户展示了他们公司的架构图
![架构图](memory/images/2026-12-01_architecture.png)
**从中提取的关键信息**:
- 使用微服务架构
- 数据库用 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 从「工具」到「同事」的范式转变

核心要点回顾

  1. 四层记忆架构:从「记不住」到「越用越懂你」
  2. 技能自动生成:从「每次从零开始」到「积累可复用经验」
  3. 多平台网关:一个 Agent,多个触达渠道
  4. 生产级部署: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 字

如果你觉得这篇文章对你有帮助,欢迎在 程序员茄子 上关注我们,获取更多深度技术文章。

推荐文章

开发外贸客户的推荐网站
2024-11-17 04:44:05 +0800 CST
Golang Select 的使用及基本实现
2024-11-18 13:48:21 +0800 CST
Rust开发笔记 | Rust的交互式Shell
2024-11-18 19:55:44 +0800 CST
HTML + CSS 实现微信钱包界面
2024-11-18 14:59:25 +0800 CST
程序员茄子在线接单