Hermes Agent源码探秘之记忆与技能学习能力
在前一篇文章中,我们聊到Agent每次启动都是一张白纸——它不知道你是谁,不记得上次说了什么,一切从零开始。但现实世界里的助理,无论是人类还是数字化的,记忆和学习能力都是必备项。

这里要揭示两个关键机制,正是它们让Hermes摆脱了“每次都是陌生人”的困境:
| 机制 | 作用 | 类比人类 |
|---|---|---|
| Memory(记忆) | 记住用户偏好、事实信息 | 长期记忆 |
| Skills(技能) | 学会完成特定任务的流程 | 肌肉记忆/操作规程 |
这篇就深入拆解这两个系统,看看它们到底是怎么运作的。
一、记忆系统(Memory)
1.1 记忆解决什么问题?
每次Agent会话相互独立,如果没有记忆系统,就会出现这种尴尬场面:
第一次对话:你:我喜欢简洁的回答
Agent:好的,记住了!
第二天:你:帮我查一下资料
Agent:好的!(又变成啰嗦模式了)
——它忘了你的偏好
有了记忆,情况就完全不一样了:
第一次对话:你:我喜欢简洁的回答
记忆:存储在数据库中
第二天:你:帮我查一下资料
Agent:加载记忆 → "用户喜欢简洁" → 简洁回答
简单说,记忆系统解决了跨会话信息持续性的问题,让Agent能真正记住用户。
1.2 记忆系统的架构
记忆系统的核心实现在 agent/memory_manager.py,它本身不直接存储数据,而是委托给存储提供者(provider):
class MemoryManager:
def __init__(self, provider):
self.provider = provider # 存储后端
def get_relevant_memories(self, query, limit=5):
"""根据当前对话获取相关记忆"""
return self.provider.search(query, limit)
def sa ve_memory(self, content, metadata=None):
"""保存新记忆"""
return self.provider.sa ve(content, metadata)
def update_memory(self, memory_id, content):
"""更新已有记忆"""
return self.provider.update(memory_id, content)
这种解耦设计意味着什么呢?它支持多种存储后端,可以根据实际需求灵活选择:
# 不同存储后端
class BuiltinMemoryProvider:
"""使用本地 SQLite 存储(默认)"""
def search(self, query, limit):
# 简单的关键词匹配
...
def sa ve(self, content, metadata):
# 写入 SQLite
...
class HonchoMemoryProvider:
"""使用 Honcho(一个专门的记忆服务)"""
def search(self, query, limit):
# 向量相似度搜索
...
class Mem0MemoryProvider:
"""使用 Mem0 记忆服务"""
def search(self, query, limit):
# Mem0 的语义搜索
...
从简单的本地SQLite到专业的向量搜索服务,从小项目到大规模应用都能找到合适方案。
1.3 记忆在对话中的注入流程
当用户发起对话时,记忆系统会经历这样一个完整流程:
用户发消息
│
▼
build_memory_context_block()
│ 从记忆库中搜索与当前话题相关的记忆
│ 比如用户问"帮我写个Python脚本"
│ 记忆:用户是Python开发者,喜欢Type hints
▼
搜索到的记忆注入到 System Prompt
│
▼
Agent 看到记忆 → 据此调整回答风格
关键代码在 agent/memory_manager.py 的 build_memory_context_block():
def build_memory_context_block(memory_manager, user_message, user_profile=None):
context_parts = []
# 1. 加载用户画像(偏好、风格等)
if user_profile:
context_parts.append(f"## 用户信息\n{user_profile}")
# 2. 搜索相关记忆
memories = memory_manager.get_relevant_memories(user_message)
if memories:
memory_text = "\n".join([f"- {m.content}" for m in memories])
context_parts.append(f"## 相关记忆\n{memory_text}")
return "\n\n".join(context_parts)
注入后的 System Prompt 看起来会是这样:
...
【用户信息】
用户是全栈开发者,擅长Python和Ja vaScript
喜欢简洁的回答风格
偏好FastAPI而非Flask
【相关记忆】
- 用户之前在做一个炒股小工具
- 用户对AI Agent源码感兴趣,在写一个拆解系列
...
Agent在收到指令前就已经“知道”了用户的背景和偏好,自然能给出更贴切的回应。
1.4 记忆的保存时机
记忆不会自动保存每一句话——那样会存太多噪声。Hermes在特定的时机才会保存记忆:
- 用户主动要求:比如"记住我喜欢简洁的回答" →
memory_tool工具被调用 - Agent判断有价值的信息:在对话结束时,Agent会自动总结有价值的记忆点
- 明确的偏好更正:当用户纠正Agent的行为时
memory_tool 的实现也很简洁:
# tools/memory_tool.py
def sa ve_memory(content: str, target: str = "memory", task_id: str = None) -> str:
"""保存一段记忆到持久存储"""
memory_manager.sa ve(
content=content,
metadata={
"target": target, # "memory" 或 "user"
"timestamp": time.time(),
"source": "user_request"
}
)
return json.dumps({"status": "sa ved"})
这种选择性保存策略有效避免了信息过载。
二、技能系统(Skills)
如果说记忆是“记住事实”,那技能就是“学会做事”。两者紧密配合,缺一不可。
2.1 什么是“技能”?
技能就是一个Markdown文件,描述如何完成某个特定任务:
~/.hermes/skills/
├── writing-plans/
│ └── SKILL.md ← 技能文件
├── test-driven-development/
│ └── SKILL.md
├── systematic-debugging/
│ └── SKILL.md
└── ...
每个技能的核心文件是 SKILL.md,包含两部分:YAML前置元数据和Markdown正文。
2.2 技能文件结构
---
name: test-driven-development
description: TDD 工作流:先写测试,再写代码,然后重构
version: 1.0.0
---
# TDD 工作流
当你需要实现一个新功能时,按以下步骤执行:
## Step 1:写测试(RED)
- 先写一个会失败的测试用例
- 明确输入和期望输出
- 运行测试,确认是红色(失败)
## Step 2:写实现(GREEN)
- 写刚好能让测试通过的代码
- 不要过度设计
- 运行测试,确认是绿色(通过)
## Step 3:重构(REFACTOR)
- 在测试保护下优化代码
- 提高可读性和性能
- 确保测试仍然通过
## 注意事项
- ❌ 不要跳过测试先写实现
- ❌ 不要一次写太多代码
- ✅ 每次只做一个功能点
结构化、清晰、可执行,这就是一个合格技能文件的标准模板。
2.3 技能的加载流程
# agent/skill_utils.py
def get_all_skills_dirs():
"""扫描所有技能目录"""
skills_dir = get_skills_dir()
return [d for d in skills_dir.iterdir() if d.is_dir()]
def load_skill(skill_dir):
"""加载一个技能"""
skill_file = skill_dir / "SKILL.md"
if not skill_file.exists():
return None
with open(skill_file, "r") as f:
content = f.read()
# 解析 frontmatter 和正文
frontmatter, body = parse_frontmatter(content)
return {
"name": frontmatter.get("name", skill_dir.name),
"description": frontmatter.get("description", ""),
"content": body,
"path": skill_dir
}
2.4 技能注入 System Prompt
当Agent加载了一个技能,这个技能的内容就会被注入到System Prompt中:
# agent/system_prompt.py
def build_skills_section(enabled_skills):
"""构建技能部分的 system prompt"""
parts = []
for skill_name in enabled_skills:
skill = load_skill(skill_name)
if skill:
parts.append(f"""
## 技能:{skill['name']}
{skill['description']}
{skill['content']}
""")
if parts:
return "以下是你需要遵循的技能指南:\n" + "\n---\n".join(parts)
return ""
所以“教Agent新技能”本质上就是往System Prompt里塞了一段Markdown文本。LLM看到这段指令,就会按照其中的步骤执行任务。简单,但非常有效。
2.5 技能的生命周期管理
Hermes还有个Curator(策展人)系统,专门管理技能的整个生命周期:
hermes curator status # 查看技能状态
hermes curator run # 手动执行一次维护
hermes curator pin name # 固定技能(不被自动清理)
hermes curator unpin name # 解锁
Curator会执行以下操作:
- 跟踪技能使用频率:不常用的技能会被标记为“空闲”
- 自动归档:长时间不用的技能自动移入归档目录
- 备份:定期打包备份所有技能,防止丢失
# agent/curator.py
class Curator:
def __init__(self, skills_dir):
self.skills_dir = skills_dir
self.usage_db = UsageTracker() # SQLite 记录使用情况
def run_maintenance(self):
"""执行维护任务"""
for skill in self._get_all_skills():
stats = self.usage_db.get_stats(skill.name)
# 判断技能是否应该归档
if stats.is_idle():
self._archive_skill(skill)
# 判断技能是否应该标记为过期
if stats.is_stale():
self._mark_stale(skill)
def _archive_skill(self, skill):
"""将技能移入归档目录"""
shutil.move(skill.path, ARCHIVE_DIR / skill.name)
self.usage_db.set_state(skill.name, "archived")
三、记忆 vs 技能:对比与协同
| 维度 | 记忆(Memory) | 技能(Skills) |
|---|---|---|
| 存储内容 | 事实、偏好、用户信息 | 操作流程、步骤、规范 |
| 存储格式 | 键值对/向量 | Markdown 文件 |
| 检索方式 | 语义搜索(相关度) | 精确匹配(按名称加载) |
| 生命周期 | 永久保存 | 由 Curator 管理 |
| 修改方式 | memory_tool 工具 | 直接编辑 SKILL.md |
| 适用场景 | "用户喜欢什么" | "怎么完成某任务" |
它们怎么协同工作?看一个完整的例子就明白了:
用户说:"写个Python脚本处理CSV"
1. Memory 系统介入:
→ 搜索记忆 → "用户是Python开发者"
→ 搜索记忆 → "用户之前做过类似的数据处理"
→ 注入到 System Prompt
2. 如果已加载 "python-best-practices" 技能:
→ 技能内容注入到 System Prompt
→ "使用类型注解、写docstring、用pathlib"
3. Agent 开始工作
→ "用户是Python开发者" → 代码风格符合
→ "有最佳实践技能" → 结构规范
→ 输出质量更高
记忆提供了“上下文”,技能提供了“能力”。两者结合,Agent才能越来越懂你、越来越能干。
四、这个设计好在哪里?
1. 记忆即插即用
多种存储后端可选(内置SQLite、Honcho、Mem0),从小项目到大规模都可以。
2. 技能即文档
用Markdown教Agent做事,门槛极低——写文档就是在训练AI。
3. 自动化的生命周期管理
Curator自动管理技能的“生老病死”,不用手动清理。
4. 零代码扩展
添加记忆不需要改代码,添加技能只需要创建Markdown文件。这意味着非技术人员也能参与Agent的“训练”。
五、下一篇预告
Agent有手(工具系统),有脑(核心循环),有记忆(Memory & Skills),还能服务多平台(Gateway)。但有时候,一个Agent不够用怎么办?
一个复杂的任务往往需要多个人协作完成。
第八篇我们拆解子袋里系统(Delegation)——"Agent生Agent"的机制。看看Hermes怎么派出多个“子Hermes”并行干活,然后把结果汇总回来。
游乐网为非赢利性网站,所展示的游戏/软件/文章内容均来自于互联网或第三方用户上传分享,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系youleyoucom@outlook.com。
同类文章
大模型API连续对话交互:上下文持久化与Token节流实践
一、引言 现在的大模型应用落地上,光靠单次独立问答已经远远不够用了。无论是办公协同的智能体、行业咨询机器人、专属业务问答系统,还是私有化部署的大模型,都得能支撑连续多轮对话、跨会话二次访问、长周期上下文关联问答这些核心能力。 在实际对话中,大家都会碰到一些共性问题:第一轮提问回复正常,第二轮就完全没
代驾系统搭建方案:订单调度与司机匹配机制
在城市夜生活日益丰富的当下,代驾早已超越“酒后找人代开”的单一场景,逐步演变为高频、即时、强时效的本地生活服务。无论是商务应酬后的返程,还是临时需要安全送车回家,用户最核心的诉求始终围绕三点:能否快速响应、司机是否靠谱、整个流程是否稳定。对于系统开发者而言,代驾平台搭建的难点恰恰也在于此——它并非简
独立开发者上云避坑:阿里云OPC节省两周配置时间
独立项目上云,说起来简单,做起来全是坑。一位拥有5年后端经验的开发者,三个月前启动了自己的“一人公司”——一个AI辅助写作SaaS,技术栈是Python Flask PostgreSQL React。本以为从本地迁移到云端就是几步操作的事,结果踩了一个又一个坑,硬生生折腾了好几周。以下是他踩坑后的复
阿里云DNS个人版19.9元/年 公网权威解析功能安全与续费说明
许多用户最近都在咨询阿里云云解析DNS个人版的价格与续费问题,这里统一整理关键信息。个人版当前新用户优惠价仅为19 9元 年,但该优惠仅限首次购买,原价实际为48元 年。因此续费时若无额外折扣,将按48元 年计费。简单来说,首年19 9元即可入手,第二年恢复原价。0 云解析DNS个人版费用阿里云云
阿里云Qwen3.7-Max深度测评:极致推理与企业级部署落地指南
Qwen3 7-Max是阿里云百炼平台最新推出的旗舰级大模型,也是Qwen3 7系列中规模最大、综合能力最强的“顶配选手”。目前开放的是纯文本模型能力,但别被这个限制误导——它面向智能体时代设计,在编程、办公生产力、长周期自主执行等场景下,表现相当能打。推理能力、多模态理解、复杂任务处理都有显著升级
- 日榜
- 周榜
- 月榜
1
2
3
4
5
6
7
8
9
10
1
2
3
4
5
6
7
8
9
10
1
2
3
4
5
6
7
8
9
10
相关攻略
2026-07-07 15:44
2026-07-07 15:44
2026-07-07 15:44
2026-07-07 15:44
2026-07-07 15:44
2026-07-07 15:43
2026-07-07 15:43
2026-07-07 15:43
热门教程
- 游戏攻略
- 安卓教程
- 苹果教程
- 电脑教程
热门话题

